Develop and Download Open Source Software

Browse CVS Repository

Annotation of /shiki/shiki/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.20 - (hide annotations) (download) (as text)
Sun Feb 18 10:16:43 2007 UTC (17 years, 1 month ago) by aloha
Branch: MAIN
CVS Tags: HEAD
Changes since 1.19: +6 -4 lines
File MIME type: text/x-csrc
fixed double free bug in Shiki_delete_buffer() (g_hash_table_remove and g_free(tabpage_label), g_free(tabInfo->name) even through share same string !)

1 aloha 1.1 /* vim: set encoding=utf8:
2     *
3     * buffer.c
4     *
5     * This file is part of Shiki.
6     *
7     * Copyright(C)2006 WAKATSUKI toshihiro
8     *
9     * Permission is hereby granted, free of charge, to any person obtaining a
10     * copy of this software and associated documentation files (the "Software"),
11     * to deal in the Software without restriction, including without limitation
12     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13     * and/or sell copies of the Software, and to permit persons to whom the
14     * Software is furnished to do so, subject to the following conditions:
15     *
16     * The above copyright notice and this permission notice shall be included in
17     * all copies or substantial portions of the Software.
18     *
19     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25     * SOFTWARE.
26     *
27 aloha 1.20 * $Id: buffer.c,v 1.19 2007/02/18 10:07:11 aloha Exp $
28 aloha 1.1 */
29     #include"shiki.h"
30 aloha 1.2
31 aloha 1.7 /* GtkTextBuffer ��������������������� ShikiBuffer ��������������������� */
32     static gint compBuffer(gconstpointer a, gconstpointer b) {
33     return ((ShikiBuffer *)a)->text_buffer == b ? 0 : b - a;
34     }
35 aloha 1.3
36 aloha 1.7 static GList *get_ShikiBufferListElement_By_GtkTextBuffer(GtkTextBuffer *b) {
37     return g_list_find_custom(Shiki_EDITOR_BUFFER_LIST, b, compBuffer);
38 aloha 1.3 }
39 aloha 1.4
40 aloha 1.9 /* ������������������������������������������������������������������������������������������ */
41     static gboolean delete_event_handler(GtkWidget *widget, GdkEvent *event, GtkTextBuffer *buffer){
42     /* delete-event ������������������������FALSE ��������������������������������������������� */
43     return Shiki_need_buffer_save_p(buffer) && !Shiki_yes_or_no_p("��������������������������������������������������������������������������� ?");
44     }
45    
46     /* ��������������������������������������������� */
47     static void insert_text_handler(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *str, gint len) {
48     /* Undo ��������������������������� */
49     ShikiUndoInfo *undoInfo = g_malloc(sizeof(ShikiUndoInfo));
50     g_return_if_fail(undoInfo != NULL);
51     undoInfo->action = SHIKI_UNDO_INSERT;
52     undoInfo->str = g_strdup(str);
53     undoInfo->strlen = len;
54     undoInfo->start = gtk_text_iter_get_offset(iter);
55     undoInfo->end = undoInfo->start + undoInfo->strlen;
56 aloha 1.14
57     if(Shiki_CURRENT_UNDO_INFO_LIST) {
58     GList *p = Shiki_CURRENT_UNDO_INFO_LIST->prev;
59     Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo);
60     Shiki_CURRENT_UNDO_INFO_LIST->prev = p;
61     } else
62     Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo);
63 aloha 1.9 }
64    
65 aloha 1.14 /* ������������������������������������������������ */
66     static void delete_range_handler(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end) {
67     /* Undo ��������������������������� */
68     ShikiUndoInfo *undoInfo = g_malloc(sizeof(ShikiUndoInfo));
69     g_return_if_fail(undoInfo != NULL);
70     undoInfo->action = SHIKI_UNDO_DELETE;
71     undoInfo->str = gtk_text_buffer_get_text(buffer, start, end, FALSE);
72     undoInfo->start = gtk_text_iter_get_offset(start);
73     undoInfo->end = gtk_text_iter_get_offset(end);
74     undoInfo->strlen = end - start;
75    
76     if(Shiki_CURRENT_UNDO_INFO_LIST) {
77     GList *p = Shiki_CURRENT_UNDO_INFO_LIST->prev;
78     Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo);
79     Shiki_CURRENT_UNDO_INFO_LIST->prev = p;
80     } else
81     Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo);
82     }
83 aloha 1.12
84     void Shiki_undo() {
85     GtkTextIter start, end;
86 aloha 1.14 ShikiUndoInfo *undoInfo;
87     GList *p;
88     if(!Shiki_CURRENT_UNDO_INFO_LIST) {
89 aloha 1.12 Shiki_msgbox("������������ Undo ���������������");
90     return;
91     }
92 aloha 1.14 undoInfo = Shiki_CURRENT_UNDO_INFO_LIST->data;
93 aloha 1.12 if(undoInfo->action == SHIKI_UNDO_UNDO) {
94 aloha 1.14 GList *l = g_list_nth(Shiki_CURRENT_UNDO_INFO_LIST, 2);
95     if(l)
96     Shiki_CURRENT_UNDO_INFO_LIST = l;
97     else {
98     Shiki_msgbox("������������ Undo ���������������");
99     return;
100     }
101     } else if(undoInfo->action == SHIKI_UNDO_REDO) {
102     GList *l = g_list_next(Shiki_CURRENT_UNDO_INFO_LIST);
103     if(l)
104     Shiki_CURRENT_UNDO_INFO_LIST = l;
105     else {
106     Shiki_msgbox("������������ Undo ���������������");
107     return;
108     }
109     }
110    
111     undoInfo = Shiki_CURRENT_UNDO_INFO_LIST->data;
112    
113     gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &start, undoInfo->start);
114     gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &end, undoInfo->end);
115    
116     if(!Shiki_CURRENT_UNDO_INFO_LIST->next) {
117     p = Shiki_CURRENT_UNDO_INFO_LIST;
118     Shiki_CURRENT_UNDO_INFO_LIST = g_list_next(Shiki_CURRENT_UNDO_INFO_LIST);
119     } else {
120     Shiki_CURRENT_UNDO_INFO_LIST = g_list_next(Shiki_CURRENT_UNDO_INFO_LIST);
121     p = Shiki_CURRENT_UNDO_INFO_LIST->prev;
122 aloha 1.12 }
123 aloha 1.14
124     if(undoInfo->action == SHIKI_UNDO_INSERT)
125     gtk_text_buffer_delete(Shiki_CURRENT_TEXT_BUFFER, &start, &end);
126     else if(undoInfo->action == SHIKI_UNDO_DELETE)
127     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &start, undoInfo->str, -1);
128    
129     Shiki_CURRENT_UNDO_INFO_LIST->prev = p;
130    
131     undoInfo = g_malloc(sizeof(ShikiUndoInfo));
132     g_return_if_fail(undoInfo != NULL);
133     undoInfo->action = SHIKI_UNDO_UNDO;
134    
135     p = Shiki_CURRENT_UNDO_INFO_LIST->prev;
136     Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo);
137     Shiki_CURRENT_UNDO_INFO_LIST->prev = p;
138    
139     { /* Debug print */
140     GList *l = Shiki_CURRENT_UNDO_INFO_LIST;
141     while(l->prev) l = l->prev;
142     g_print("Undo : NULL -> ");
143     for(; l != NULL; l = l->next) {
144     if(l == Shiki_CURRENT_UNDO_INFO_LIST)
145     g_print(" | ");
146     switch(((ShikiUndoInfo *)l->data)->action) {
147     case SHIKI_UNDO_UNDO :
148     g_print("[U] -> ");
149     break;
150     case SHIKI_UNDO_REDO :
151     g_print("[R] -> ");
152     break;
153     case SHIKI_UNDO_INSERT :
154     g_print("[+] -> ");
155     break;
156     case SHIKI_UNDO_DELETE :
157     g_print("[-] -> ");
158     break;
159     }
160     }
161     g_print("NIL\n");
162     }
163     }
164    
165     void Shiki_redo() {
166     GtkTextIter start, end;
167     ShikiUndoInfo *undoInfo;
168     GList *p;
169     if(!Shiki_CURRENT_UNDO_INFO_LIST) {
170     Shiki_msgbox("������������ Redo ���������������");
171 aloha 1.12 return;
172 aloha 1.14 }
173     undoInfo = Shiki_CURRENT_UNDO_INFO_LIST->data;
174     if(undoInfo->action == SHIKI_UNDO_UNDO)
175     undoInfo = g_list_nth_data(Shiki_CURRENT_UNDO_INFO_LIST, 1);
176     else if(undoInfo->action == SHIKI_UNDO_REDO) {
177     GList *l = g_list_nth_prev(Shiki_CURRENT_UNDO_INFO_LIST, 3);
178     if(l) {
179     Shiki_CURRENT_UNDO_INFO_LIST = l;
180     undoInfo = g_list_nth_data(Shiki_CURRENT_UNDO_INFO_LIST, 1);
181     } else {
182     Shiki_msgbox("������������ Redo ���������������");
183     return;
184     }
185     }
186    
187 aloha 1.12 gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &start, undoInfo->start);
188     gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &end, undoInfo->end);
189    
190 aloha 1.14 p = Shiki_CURRENT_UNDO_INFO_LIST->prev;
191    
192     if(undoInfo->action == SHIKI_UNDO_INSERT)
193 aloha 1.12 gtk_text_buffer_delete(Shiki_CURRENT_TEXT_BUFFER, &start, &end);
194 aloha 1.14 else if(undoInfo->action == SHIKI_UNDO_DELETE)
195     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &start, undoInfo->str, -1);
196    
197     undoInfo = g_malloc(sizeof(ShikiUndoInfo));
198     g_return_if_fail(undoInfo != NULL);
199     undoInfo->action = SHIKI_UNDO_REDO;
200    
201     Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo);
202    
203     Shiki_CURRENT_UNDO_INFO_LIST->prev = p;
204    
205     { /* Debug ptirt */
206     GList *l = Shiki_CURRENT_UNDO_INFO_LIST;
207     while(l->prev) l = l->prev;
208     g_print("Redo : NULL -> ");
209     for(; l != NULL; l = l->next) {
210     if(l == Shiki_CURRENT_UNDO_INFO_LIST)
211     g_print(" | ");
212     switch(((ShikiUndoInfo *)l->data)->action) {
213     case SHIKI_UNDO_UNDO :
214     g_print("[U] -> ");
215     break;
216     case SHIKI_UNDO_REDO :
217     g_print("[R] -> ");
218     break;
219     case SHIKI_UNDO_INSERT :
220     g_print("[+] -> ");
221     break;
222     case SHIKI_UNDO_DELETE :
223     g_print("[-] -> ");
224     break;
225     }
226     }
227     g_print("NIL\n");
228     }
229 aloha 1.12 }
230    
231 aloha 1.9 /* ��������������������������������������������������������������� */
232 aloha 1.15 void Shiki_update_modeline() {
233 aloha 1.16 gchar *mlf;
234     ScmEvalPacket packet;
235     gint result = Scm_EvalCString("(if *mode-line-format* (*mode-line-format*) \"\")", Shiki_CURRENT_BUFFER_ENV, &packet);
236    
237     if(result == -1) {
238     ScmObj os = Scm_MakeOutputStringPort(TRUE);
239     Scm_Write(packet.exception, os, SCM_WRITE_DISPLAY);
240     mlf = Scm_GetString(SCM_STRING(Scm_GetOutputString(SCM_PORT(os))));
241     } else
242     mlf = Scm_GetString(SCM_STRING(packet.results[0]));
243    
244     gtk_label_set_text(GTK_LABEL(Shiki_EDITOR_MODELINE_LABEL), mlf);
245 aloha 1.9 }
246    
247 aloha 1.11 static void cursor_moved_handler() {
248 aloha 1.15 Shiki_update_modeline();
249 aloha 1.11 }
250    
251 aloha 1.9 /* ��������������������������������������� (������������) ��������� */
252     GtkTextBuffer *Shiki_new_buffer_create(gchar *filename) {
253 aloha 1.18
254 aloha 1.9 /*-------------------- ������������������������ ----------------------------------*/
255     /* ShikiBuffer ������������������������������������������������������������������ */
256     ShikiBuffer *tabinfo = g_malloc(sizeof(ShikiBuffer));
257     tabinfo->locale = "Gtk Default (utf8)";
258     tabinfo->undoInfoList = NULL;
259     tabinfo->filename = filename;
260     tabinfo->name = g_path_get_basename(filename);
261 aloha 1.19 //tabinfo->tabpage_label = g_strndup(tabinfo->name, 10);
262 aloha 1.9 tabinfo->env = Scm_MakeModule(NULL, FALSE);
263 aloha 1.14
264 aloha 1.18 /* ��������������������������������� */
265     if(g_hash_table_lookup(Shiki_EDITOR_BUFNAME_HASH, tabinfo->name) == NULL)
266     g_hash_table_insert(Shiki_EDITOR_BUFNAME_HASH, tabinfo->name, GUINT_TO_POINTER(TRUE));
267     else {
268     gint i = 1;
269     gchar *base = tabinfo->name;
270     while(TRUE) {
271     tabinfo->name = g_strdup_printf ("%s<%d>", base, i);
272     if(g_hash_table_lookup(Shiki_EDITOR_BUFNAME_HASH, tabinfo->name) == NULL) {
273     g_hash_table_insert(Shiki_EDITOR_BUFNAME_HASH, tabinfo->name, GUINT_TO_POINTER(TRUE));
274     g_free(base);
275     break;
276     }
277     g_free(tabinfo->name);
278     i++;
279     }
280     }
281    
282 aloha 1.19 tabinfo->tabpage_label = tabinfo->name;
283 aloha 1.18
284 aloha 1.17 /* ��������� GC ��������������������� */
285     Scm_Define(SCM_CURRENT_MODULE(), SCM_SYMBOL(SCM_INTERN(tabinfo->name)), tabinfo->env);
286    
287 aloha 1.9 /* xyzzy lisp ��������������� */
288     Scm_Init_xyzzylisp(SCM_MODULE(tabinfo->env));
289    
290     /* ������������������������������ (������������������������) ��������� */
291     tabinfo->tabpage = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
292     gtk_scrolled_window_set_policy (tabinfo->tabpage, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
293    
294     /* ��������������������������������������������������������������������������������������� */
295     tabinfo->text_view = GTK_TEXT_VIEW(gtk_text_view_new());
296     gtk_text_view_set_wrap_mode(tabinfo->text_view, GTK_WRAP_WORD);
297     tabinfo->text_buffer = gtk_text_view_get_buffer(tabinfo->text_view);
298     gtk_widget_set_size_request(GTK_WIDGET(tabinfo->text_view), 680, 700);
299    
300     gtk_container_add(GTK_CONTAINER(tabinfo->tabpage), GTK_WIDGET(tabinfo->text_view));
301 aloha 1.11 g_signal_connect(tabinfo->text_buffer, "mark_set", G_CALLBACK(cursor_moved_handler), tabinfo->text_view);
302 aloha 1.9 g_signal_connect(tabinfo->text_buffer, "insert-text", G_CALLBACK(insert_text_handler), NULL);
303     g_signal_connect(tabinfo->text_buffer, "delete-range", G_CALLBACK(delete_range_handler), NULL);
304    
305     /* ������������������������������������������������������������������������������������������������������ */
306     tabinfo->delete_handler_id = g_signal_connect(Shiki_EDITOR_WINDOW, "delete_event", G_CALLBACK(delete_event_handler), tabinfo->text_buffer);
307    
308     /* ������������������������ */
309    
310     /* ������������������������������������������������ */
311     gtk_text_buffer_create_tag(tabinfo->text_buffer, "parent_emphasis_background", "background", "green", NULL);
312    
313 aloha 1.13 /* ������/������������������������������������ */
314     gtk_text_buffer_create_tag(tabinfo->text_buffer, "match_highlighting", "background", "pink", NULL);
315    
316 aloha 1.9 /* ������������������������������������������ */
317     gtk_text_buffer_create_tag(tabinfo->text_buffer, "keyword_highlighting", "foreground", "blue", NULL);
318     /* ������ */
319     gtk_text_buffer_create_tag(tabinfo->text_buffer, "function_highlighting", "foreground", "red", NULL);
320     /* ������������ */
321     gtk_text_buffer_create_tag (tabinfo->text_buffer, "comment_highlighting", "foreground", "purple", NULL);
322     /* ��������� */
323     gtk_text_buffer_create_tag (tabinfo->text_buffer, "string_highlighting", "foreground", "orange", NULL);
324     /* ������������������������������������������ */
325     gtk_notebook_append_page(Shiki_EDITOR_NOTEBOOK, GTK_WIDGET(tabinfo->tabpage), gtk_label_new(tabinfo->tabpage_label));
326     /* ������������������������������������������������������������������ */
327     Shiki_EDITOR_BUFFER_LIST = g_list_append(Shiki_EDITOR_BUFFER_LIST, tabinfo);
328    
329     gtk_widget_show_all(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK));
330     /* ��������������������������������� */
331     gtk_notebook_set_current_page(Shiki_EDITOR_NOTEBOOK, g_list_length(Shiki_EDITOR_BUFFER_LIST) - 1);
332     //Shiki_CURRENT_TAB_INFO = tabinfo;
333 aloha 1.14
334 aloha 1.16 if(-1 == Scm_EvalCString("(set! *mode-line-format* (lambda () (format #f \"--~A- ~A (Gauche Interaction) [GtkDefault (utf8)] L~S:~S \" (if (buffer-modified-p) \"--\" \"**\") (buffer-name (selected-buffer)) (current-line-number) (current-column))))", tabinfo->env, NULL))
335     fprintf(stderr, "Fatal error : mode-line-format initialize in Shiki_new_buffer_create()");
336 aloha 1.9 return tabinfo->text_buffer;
337     }
338    
339 aloha 1.10 void Shiki_create_file_buffer(const gchar *filename) {
340 aloha 1.16 gchar *text, *utf8filename = g_locale_to_utf8(filename, -1, NULL, NULL, NULL);
341 aloha 1.10 GtkTextIter p;
342 aloha 1.16 ScmEvalPacket packet;
343     gint result;
344 aloha 1.10
345     /* g_file_get_contents(filename, &contents, &len, NULL); */
346    
347     /* ������������������������������ */
348     Shiki_new_buffer_create(g_strdup(filename));
349     gtk_window_set_title (GTK_WINDOW (Shiki_EDITOR_WINDOW), filename);
350    
351     Scm_Define(SCM_MODULE(Shiki_CURRENT_BUFFER_ENV), SCM_SYMBOL(SCM_INTERN("*filename*")), SCM_MAKE_STR_COPYING(utf8filename));
352     g_free(utf8filename);
353    
354 aloha 1.16 if(-1 == Scm_EvalCString("(use gauche.charconv)", Shiki_CURRENT_BUFFER_ENV, NULL))
355     fprintf(stderr, "Fatal error : can't use gauche.charconv module in Shiki_create_file_buffer()");
356 aloha 1.10
357     /* ������������������������������������������������������������������������������ */
358 aloha 1.16 result = Scm_EvalCString("(port->string (open-input-conversion-port (open-input-file *filename*) \"*jp\" :owner? #t))", Shiki_CURRENT_BUFFER_ENV, &packet);
359     if(result != -1) {
360     text = Scm_GetString(SCM_STRING(packet.results[0]));
361 aloha 1.10 gtk_text_buffer_set_text(Shiki_CURRENT_TEXT_BUFFER, text, -1);
362 aloha 1.16 } else {
363 aloha 1.10 /* open-input-conversion-port ������������������������������������������������������
364     * ��������������������������������������������������������������������������� UTF8
365     */
366     gchar *contents;
367     gsize br, bw, len;
368     GError *err = NULL;
369    
370     if(g_file_get_contents(filename, &contents, &len, NULL)) {
371     if(!(text = g_locale_to_utf8(contents, -1, &br, &bw, &err)))
372 aloha 1.13 gtk_text_buffer_set_text(Shiki_CURRENT_TEXT_BUFFER, text, -1);
373 aloha 1.10 else
374 aloha 1.13 gtk_text_buffer_set_text(Shiki_CURRENT_TEXT_BUFFER, contents, -1);
375 aloha 1.10 g_free(contents);
376     }
377     }
378    
379     /* ������������������������ */
380     gtk_text_buffer_set_modified(Shiki_CURRENT_TEXT_BUFFER, FALSE);
381     /* ������������������������������ */
382     gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &p);
383     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
384 aloha 1.11 Shiki_update_modeline(Shiki_CURRENT_TEXT_BUFFER);
385 aloha 1.10 gtk_widget_show_all(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK));
386     }
387    
388     void Shiki_open_file_dialog() {
389     const gchar *filename = Shiki_file_name_dialog("���������������������");
390    
391     if(!filename) return;
392     Shiki_create_file_buffer(filename);
393     }
394    
395 aloha 1.7 void Shiki_delete_buffer(GtkTextBuffer *buffer) {
396     /* ��������������������������������������������������������������������������������������������������� */
397     /* ���������������������Scheme ������������������������ Gtk ������������������������������������������������ */
398     GList *bufListElem = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
399     ShikiBuffer *tabInfo = bufListElem->data;
400     gint bufNum = g_list_position(Shiki_EDITOR_BUFFER_LIST, bufListElem);
401    
402 aloha 1.18 /* g_print("%d page delete.\n", bufNum); */
403    
404     g_print("buffer list length = %d\n", g_list_length(Shiki_EDITOR_BUFFER_LIST));
405 aloha 1.7 /* ��������� 1 ��������������������������������������������������� */
406     if(g_list_length(Shiki_EDITOR_BUFFER_LIST) == 1)
407 aloha 1.4 return;
408 aloha 1.17
409     /* Scheme ������������������������ */
410     Scm_Define(SCM_CURRENT_MODULE(), SCM_SYMBOL(SCM_INTERN(tabInfo->name)), SCM_FALSE);
411    
412 aloha 1.18 /* ������������������������ */
413     g_hash_table_remove(Shiki_EDITOR_BUFNAME_HASH, tabInfo->name);
414 aloha 1.7 /* ��������������������������������������������������������������������������������������������� */
415     g_signal_handler_disconnect(Shiki_EDITOR_WINDOW, tabInfo->delete_handler_id);
416 aloha 1.18 Shiki_EDITOR_BUFFER_LIST = g_list_delete_link(Shiki_EDITOR_BUFFER_LIST, bufListElem);
417    
418     /* double delete bug ! */
419     /* gtk_widget_destroy(GTK_WIDGET(tabInfo->tabpage)); */
420 aloha 1.20 /* double free bugs
421     g_free(tabInfo->tabpage_label);
422     g_free(tabInfo->name);
423     */
424 aloha 1.7 g_free(tabInfo->filename);
425     g_free(tabInfo);
426     gtk_notebook_remove_page(Shiki_EDITOR_NOTEBOOK, bufNum);
427     /* ��������������� */
428     gtk_widget_queue_draw(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK));
429 aloha 1.20 /* gtk_notebook_set_current_page(Shiki_EDITOR_NOTEBOOK, bufNum > 0 ? bufNum-1 : 0); */
430 aloha 1.7 }
431    
432     GtkTextBuffer *Shiki_find_buffer(const gchar *name) {
433     GList *l;
434     for(l = Shiki_EDITOR_BUFFER_LIST; l != NULL; l = l->next)
435     if(strcmp(((ShikiBuffer *)l->data)->name, name) == 0)
436     return ((ShikiBuffer *)l->data)->text_buffer;
437     return NULL;
438     }
439    
440     gchar *Shiki_buffer_substring(gint start, gint end) {
441     if(start >= end)
442     return NULL;
443     else {
444     GtkTextIter s, e;
445     gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &s, start);
446     gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &e, end);
447    
448     return gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &s, &e, FALSE);
449     }
450     }
451    
452     void Shiki_delete_region(gint start, gint end) {
453     if(start >= end)
454     return;
455     else {
456     GtkTextIter s, e;
457     gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &s, start);
458     gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &e, end);
459 aloha 1.4
460 aloha 1.7 return gtk_text_buffer_delete(Shiki_CURRENT_TEXT_BUFFER, &s, &e);
461     }
462 aloha 1.4 }
463    
464     gint Shiki_point() {
465     GtkTextIter p;
466     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
467     return gtk_text_iter_get_offset(&p);
468     }
469    
470     gint Shiki_point_max() {
471     GtkTextIter p;
472     gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &p);
473     return gtk_text_iter_get_offset(&p);
474     }
475    
476     gint Shiki_point_min() {
477     return 0;
478     }
479    
480     void Shiki_goto_char(gint offset) {
481     GtkTextIter p;
482     gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &p, offset);
483     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
484     }
485    
486     void Shiki_forward_char() {
487     GtkTextIter p;
488     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
489     gtk_text_iter_forward_char(&p);
490     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
491     }
492    
493     void Shiki_backward_char() {
494     GtkTextIter p;
495     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
496     gtk_text_iter_backward_char(&p);
497     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
498     }
499    
500     void Shiki_goto_line(gint line) {
501     GtkTextIter p;
502     gtk_text_buffer_get_iter_at_line(Shiki_CURRENT_TEXT_BUFFER, &p, line);
503     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
504     }
505    
506     void Shiki_goto_bol() {
507     GtkTextIter p;
508     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
509     gtk_text_buffer_get_iter_at_line_offset(Shiki_CURRENT_TEXT_BUFFER, &p, gtk_text_iter_get_line(&p), 0);
510     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
511     }
512    
513     void Shiki_goto_eol() {
514     GtkTextIter p;
515     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
516     gtk_text_iter_forward_to_line_end(&p);
517     gtk_text_iter_backward_char(&p);
518     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
519     }
520 aloha 1.5
521 aloha 1.7 void Shiki_forward_line(gint count) {
522     GtkTextIter p;
523     gint i;
524     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
525 aloha 1.14
526 aloha 1.7 if(count >= 0) {
527     for(i = count; i != 0; i--)
528     gtk_text_view_forward_display_line(Shiki_CURRENT_TEXT_VIEW, &p);
529     } else {
530     for(i = count; i != 0; i++)
531     gtk_text_view_backward_display_line(Shiki_CURRENT_TEXT_VIEW, &p);
532     }
533     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
534 aloha 1.5 }
535    
536     const char *Shiki_buffer_name(GtkTextBuffer *buffer) {
537     GList *l = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
538     if(l)
539     return ((ShikiBuffer *)(l->data))->name;
540     else
541     return NULL;
542     }
543    
544 aloha 1.6 gboolean Shiki_deleted_buffer_p(GtkTextBuffer *buffer) {
545     GList *l = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
546     if(l)
547     return FALSE;
548     else
549     return TRUE;
550     }
551    
552 aloha 1.5 GtkTextBuffer *Shiki_get_next_buffer(GtkTextBuffer *buffer) {
553     GList *l = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
554     if(l && l->next)
555     return ((ShikiBuffer *)(l->next->data))->text_buffer;
556     else
557     return NULL;
558     }
559    
560     GtkTextBuffer *Shiki_get_previous_buffer(GtkTextBuffer *buffer) {
561     GList *l = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
562     if(l && l->prev)
563     return ((ShikiBuffer *)(l->prev->data))->text_buffer;
564     else
565     return NULL;
566     }
567    
568     ScmObj Shiki_buffer_list() {
569     GList *l;
570     GtkTextBuffer *b;
571     ScmObj bl = SCM_NIL;
572    
573     for(l = Shiki_EDITOR_BUFFER_LIST; l != NULL; l = l->next) {
574     b= ((ShikiBuffer *)(l->data))->text_buffer;
575     bl = Scm_Cons(SHIKI_BUFFER_BOX(g_object_ref(b)), bl);
576     }
577     return bl;
578     }
579 aloha 1.7
580     void Shiki_erase_buffer(GtkTextBuffer *buffer) {
581     GtkTextIter start, end;
582     gtk_text_buffer_get_start_iter(buffer, &start);
583     gtk_text_buffer_get_end_iter(buffer, &end);
584     gtk_text_buffer_delete(buffer, &start, &end);
585     }
586    
587     const gchar *Shiki_file_name_dialog(const gchar *msg) {
588    
589     GtkWidget *dialog = gtk_file_selection_new(msg);
590     gint resp = gtk_dialog_run(GTK_DIALOG(dialog));
591     const gchar *filename = NULL;
592    
593     if(resp == GTK_RESPONSE_OK)
594     filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dialog));
595    
596     gtk_widget_destroy(dialog);
597     return filename;
598     }
599    
600     gboolean Shiki_yes_or_no_p(const gchar *msg) {
601     GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(Shiki_EDITOR_WINDOW),
602 aloha 1.14 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
603     GTK_BUTTONS_YES_NO, msg);
604 aloha 1.9 gint resp;
605     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
606     resp = gtk_dialog_run(GTK_DIALOG(dialog));
607     gtk_widget_destroy(dialog);
608     if(GTK_RESPONSE_YES == resp)
609     return TRUE;
610     return FALSE;
611     }
612    
613     gboolean Shiki_no_or_yes_p(const gchar *msg) {
614     GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(Shiki_EDITOR_WINDOW),
615 aloha 1.14 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
616     GTK_BUTTONS_YES_NO, msg);
617 aloha 1.9 gint resp;
618     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_NO);
619     resp = gtk_dialog_run(GTK_DIALOG(dialog));
620 aloha 1.7 gtk_widget_destroy(dialog);
621     if(GTK_RESPONSE_YES == resp)
622     return TRUE;
623     return FALSE;
624     }
625 aloha 1.8
626     gboolean Shiki_need_buffer_save_p(GtkTextBuffer *buffer) {
627     return gtk_text_buffer_get_modified(buffer);
628     }
629    
630     /* ������������ */
631     void Shiki_kill_buffer(GtkTextBuffer *buffer) {
632     if(!Shiki_need_buffer_save_p(buffer) || Shiki_yes_or_no_p("��������������������������������������������������������������������������� ?"))
633     Shiki_delete_buffer(buffer);
634     }
635 aloha 1.12
636     void Shiki_msgbox(const gchar *msg) {
637     GtkWidget *dialog;
638     dialog = gtk_message_dialog_new(GTK_WINDOW(Shiki_EDITOR_WINDOW),
639     GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,msg);
640     gtk_dialog_run(GTK_DIALOG(dialog));
641     gtk_widget_destroy(dialog);
642     }
643 aloha 1.13
644     /* GtkTextCharPredicate */
645     static gboolean is_kakko_or_kokka(gunichar ch, gpointer p) {
646     return ch == '(' || ch == ')';
647     }
648     static gboolean is_kakko(gunichar ch, gpointer p) {return ch == '(';}
649     static gboolean is_kokka(gunichar ch, gpointer p) {return ch == ')';}
650     static gboolean search_sexp_kokka(GtkTextIter *end) {
651     gint nest_level = 0;
652    
653     /* ������������ ')' ��������� */
654     while(1) {
655     if(!gtk_text_iter_forward_find_char(end, is_kakko_or_kokka, NULL, NULL))
656     return FALSE;
657    
658     if(gtk_text_iter_get_char(end) == '(')
659     nest_level++;
660     else {
661     if(!nest_level)
662     break;
663     else
664     nest_level--;
665     }
666     }
667     return TRUE;
668     }
669    
670    
671     /* ')' ��������������� '(' ������������������ (S ���) ��������������� */
672     static gboolean search_last_sexp_kakko(GtkTextIter *start) {
673     gint nest_level = 0;
674     /* ��������������������������������������� ')' ��������� */
675     while(1) {
676     if(!gtk_text_iter_backward_find_char(start, is_kakko_or_kokka, NULL, NULL))
677     return FALSE;
678    
679     if(gtk_text_iter_get_char(start) == ')')
680     nest_level++;
681     else {
682     if(!nest_level)
683     break;
684     else
685     nest_level--;
686     }
687     }
688     return TRUE;
689     }
690    
691     /* ��������������������� '(' ��������������� ')' ������������������ (S ���) ��������������� */
692     static gboolean search_sexp(GtkTextIter *start, GtkTextIter *end) {
693    
694     /* ������������������������������ */
695     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, start, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
696    
697     if(gtk_text_iter_get_char(start) != '(')
698     gtk_text_iter_forward_find_char(start, is_kakko, NULL, NULL);
699    
700     *end = *start;
701    
702     /* ��������������������������������� S ������������������ */
703     if(!search_sexp_kokka(end)) return FALSE;
704     gtk_text_iter_forward_char(end);
705     return TRUE;
706     }
707    
708     /* ��������������������� ')' ��������������� '(' ������������������ (S ���) ��������������� */
709     static gboolean search_last_sexp(GtkTextIter *start, GtkTextIter *end) {
710    
711     /* ������������������������������ */
712     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, end, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
713    
714     gtk_text_iter_backward_char(end);
715    
716     if(gtk_text_iter_get_char(end) != ')')
717     gtk_text_iter_backward_find_char(end, is_kokka, NULL, NULL);
718     *start = *end;
719     gtk_text_iter_forward_char(end);
720    
721     /* ��������������������������������� S ������������������ */
722     if(!search_last_sexp_kakko(start)) return FALSE;
723    
724     return TRUE;
725     }
726    
727     /* gauche ��������������������������������� */
728     static gchar *eval_cstring_by_gauche(gchar *s) {
729     gchar *msg;
730 aloha 1.16 ScmEvalPacket packet;
731 aloha 1.13 /* ������������������������������ */
732     ScmObj os = Scm_MakeOutputStringPort(TRUE);
733 aloha 1.16 gint i, result = Scm_EvalCString(s, SCM_OBJ(Shiki_CURRENT_BUFFER_ENV), &packet);
734    
735     if(result == -1)
736     Scm_Write(packet.exception, os, SCM_WRITE_DISPLAY);
737 aloha 1.13 else
738 aloha 1.16 for(i = 0; i < packet.numResults; i++)
739     Scm_Printf(SCM_PORT(os), "%S\n", packet.results[i]);
740 aloha 1.13
741     msg = Scm_GetString(SCM_STRING(Scm_GetOutputString(SCM_PORT(os))));
742     /* ������������������ */
743     Scm_ClosePort(SCM_PORT(os));
744    
745     return msg;
746     }
747 aloha 1.16
748 aloha 1.15 void Shiki_load_file(const gchar *filename) {
749     gchar *result, *utf8filename = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
750     GtkTextIter p;
751    
752     Scm_Define(SCM_MODULE(Shiki_CURRENT_BUFFER_ENV), SCM_SYMBOL(SCM_INTERN("*filename*")), SCM_MAKE_STR_COPYING(utf8filename));
753     result = eval_cstring_by_gauche("(load *filename*)");
754    
755     gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &p);
756     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &p, "\n", -1);
757     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &p, result, -1);
758     }
759 aloha 1.13
760     void Shiki_eval_expression() {
761    
762     gchar *code, *result;
763     GtkTextIter start, end;
764    
765     if(!search_sexp(&start, &end)) return;
766    
767     code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE);
768     result = eval_cstring_by_gauche(code);
769     g_free(code);
770    
771     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &end, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
772    
773     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n", -1);
774     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, result, -1);
775     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n", -1);
776     }
777    
778     void Shiki_eval_last_sexp() {
779     gchar *code, *result;
780     GtkTextIter start, end;
781    
782     if(!search_last_sexp(&start, &end)) return;
783    
784     code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE);
785     result = eval_cstring_by_gauche(code);
786     g_free(code);
787    
788     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &end, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
789    
790     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n", -1);
791     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, result, -1);
792     gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n", -1);
793     }
794    
795     typedef enum {
796     SHIKI_SEARCH_FORWARD,
797     SHIKI_SEARCH_BACKWARD
798     } ShikiSearchDirection;
799    
800     static struct {
801     GtkWidget *input;
802     gboolean ci;
803     gboolean word;
804     gboolean regexp;
805     gboolean escape;
806     gboolean loop;
807     } ShikiSearchBufferInfo;
808    
809     gboolean Shiki_search_string(const gchar *pattern, gboolean no_dup,
810     ShikiSearchDirection direction) {
811     GtkTextIter p, match_start, match_end, start, end;
812     gboolean result;
813    
814     gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &start);
815     gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &end);
816    
817     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
818    
819     if(direction == SHIKI_SEARCH_FORWARD) {
820     if(no_dup)
821     gtk_text_iter_forward_char(&p);
822    
823     result = gtk_text_iter_forward_search(&p, pattern,
824     GTK_TEXT_SEARCH_TEXT_ONLY, &match_start, &match_end, &end);
825     } else {
826     if(no_dup)
827     gtk_text_iter_backward_char(&p);
828 aloha 1.14
829 aloha 1.13 result = gtk_text_iter_backward_search(&p, pattern,
830     GTK_TEXT_SEARCH_TEXT_ONLY, &match_start, &match_end, &start);
831     }
832    
833     if(result) {
834     gtk_text_buffer_remove_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "match_highlighting", &start, &end);
835     gtk_text_buffer_apply_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "match_highlighting", &match_start, &match_end);
836     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &match_start);
837     gtk_text_view_scroll_to_iter(Shiki_CURRENT_TEXT_VIEW, &match_start,
838 aloha 1.14 0.0, FALSE, FALSE, FALSE);
839 aloha 1.13 }
840     return result;
841     }
842    
843     static void destroy_handler(GtkWidget *button, GtkWidget *widget) {gtk_widget_destroy(widget);}
844    
845     static void toggled_handler(GtkToggleButton *togglebutton, gboolean *flag) {
846     *flag = !*flag;
847     }
848    
849     static void search_forward_handler() {
850     Shiki_search_string(gtk_entry_get_text(GTK_ENTRY(ShikiSearchBufferInfo.input)), TRUE, SHIKI_SEARCH_FORWARD);
851     }
852     static void search_backward_handler() {
853     Shiki_search_string(gtk_entry_get_text(GTK_ENTRY(ShikiSearchBufferInfo.input)), TRUE, SHIKI_SEARCH_BACKWARD);
854     }
855    
856     void Shiki_search_buffer() {
857     static GtkWidget *input = NULL;
858     GtkWidget *dialog = gtk_dialog_new_with_buttons ("������������������", GTK_WINDOW(Shiki_EDITOR_WINDOW), GTK_DIALOG_DESTROY_WITH_PARENT, NULL);
859     GtkWidget *table = gtk_table_new(6, 3, FALSE);
860     GtkWidget *label = gtk_label_new("������ : ");
861     GtkWidget *check1 = gtk_check_button_new_with_label("���������������������������������");
862     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check1), TRUE);
863     GtkWidget *check2 = gtk_check_button_new_with_label("���������������������������");
864     GtkWidget *check3 = gtk_check_button_new_with_label("������������");
865     GtkWidget *check4 = gtk_check_button_new_with_label("���������������������������������������������");
866     GtkWidget *check5 = gtk_check_button_new_with_label("���������������������������������");
867     GtkWidget *prev = gtk_button_new_with_label ("���������");
868     g_signal_connect (prev, "clicked", G_CALLBACK(search_backward_handler), NULL);
869     GtkWidget *next = gtk_button_new_with_label ("���������");
870     g_signal_connect (next, "clicked", G_CALLBACK(search_forward_handler), NULL);
871     GtkWidget *cancel = gtk_button_new_with_label ("���������������");
872 aloha 1.14
873 aloha 1.13 if(!input)
874     ShikiSearchBufferInfo.input = input = g_object_ref(gtk_entry_new());
875     ShikiSearchBufferInfo.ci =
876 aloha 1.14 ShikiSearchBufferInfo.word =
877     ShikiSearchBufferInfo.regexp =
878     ShikiSearchBufferInfo.escape =
879     ShikiSearchBufferInfo.loop = FALSE;
880 aloha 1.13
881     g_signal_connect (check1, "toggled", G_CALLBACK (toggled_handler), &(ShikiSearchBufferInfo.ci));
882     g_signal_connect (check2, "toggled", G_CALLBACK (toggled_handler), &(ShikiSearchBufferInfo.word));
883     g_signal_connect (check3, "toggled", G_CALLBACK (toggled_handler), &(ShikiSearchBufferInfo.regexp));
884     g_signal_connect (check4, "toggled", G_CALLBACK (toggled_handler), &(ShikiSearchBufferInfo.escape));
885     g_signal_connect (check5, "toggled", G_CALLBACK (toggled_handler), &(ShikiSearchBufferInfo.loop));
886    
887     g_signal_connect (G_OBJECT(dialog), "delete_event", G_CALLBACK(gtk_widget_destroy), NULL);
888     g_signal_connect (G_OBJECT(cancel), "clicked", G_CALLBACK(destroy_handler), dialog);
889     gtk_table_set_row_spacings(GTK_TABLE(table), 10);
890     gtk_table_set_col_spacings(GTK_TABLE(table), 10);
891     gtk_container_border_width (GTK_CONTAINER (dialog), 10);
892     gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 0, 1);
893     gtk_table_attach_defaults (GTK_TABLE(table), input, 1, 2, 0, 1);
894     gtk_table_attach_defaults (GTK_TABLE(table), prev, 2, 3, 0, 1);
895     gtk_table_attach_defaults (GTK_TABLE(table), check1, 1, 2, 1, 2);
896     gtk_table_attach_defaults (GTK_TABLE(table), check2, 1, 2, 2, 3);
897     gtk_table_attach_defaults (GTK_TABLE(table), check3, 1, 2, 3, 4);
898     gtk_table_attach_defaults (GTK_TABLE(table), check4, 1, 2, 4, 5);
899     gtk_table_attach_defaults (GTK_TABLE(table), check5, 1, 2, 5, 6);
900     gtk_table_attach_defaults (GTK_TABLE(table), next, 2, 3, 1, 2);
901     gtk_table_attach_defaults (GTK_TABLE(table), cancel, 2, 3, 2, 3);
902     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
903     gtk_widget_show_all(table);
904     gtk_dialog_run(GTK_DIALOG(dialog));
905     }
906    
907     static struct {
908     GtkWidget *find;
909     GtkWidget *replace;
910     gboolean ci;
911     gboolean word;
912     gboolean regexp;
913     gboolean escape;
914     gboolean from_first;
915     } ShikiReplaceBufferInfo;
916    
917     gboolean Shiki_replace_string(const gchar *find, const gchar *replace, gboolean no_dup, gboolean interactive_p, gboolean from_first_p) {
918     GtkTextIter start, end, match_start, match_end;
919     gboolean result = FALSE;
920    
921     if(from_first_p)
922     gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &start);
923     else
924     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &start, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
925    
926     gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &end);
927    
928     while((result = gtk_text_iter_forward_search(&start, find,
929 aloha 1.14 GTK_TEXT_SEARCH_TEXT_ONLY, &match_start, &match_end, &end))) {
930 aloha 1.13
931     gtk_text_buffer_remove_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "match_highlighting", &start, &end);
932     gtk_text_buffer_apply_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "match_highlighting", &match_start, &match_end);
933     gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &match_start);
934     gtk_text_view_scroll_to_iter(Shiki_CURRENT_TEXT_VIEW, &match_start,
935     0.0, FALSE, FALSE, FALSE);
936     if(!interactive_p
937     ||
938     (interactive_p && Shiki_yes_or_no_p("������������������ ?"))) {
939     gtk_text_buffer_delete(Shiki_CURRENT_TEXT_BUFFER, &match_start, &match_end);
940     gtk_text_buffer_insert_at_cursor(Shiki_CURRENT_TEXT_BUFFER, replace, -1);
941     }
942     gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &start, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
943     gtk_text_iter_forward_char(&start);
944     gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &end);
945     }
946    
947     return result;
948     }
949    
950     static void replace_interactive_handler() {
951     Shiki_replace_string(gtk_entry_get_text(GTK_ENTRY(ShikiReplaceBufferInfo.find)), gtk_entry_get_text(GTK_ENTRY(ShikiReplaceBufferInfo.replace)), TRUE, TRUE, ShikiReplaceBufferInfo.from_first);
952     }
953     static void replace_all_handler() {
954     Shiki_replace_string(gtk_entry_get_text(GTK_ENTRY(ShikiReplaceBufferInfo.find)), gtk_entry_get_text(GTK_ENTRY(ShikiReplaceBufferInfo.replace)), TRUE, FALSE, ShikiReplaceBufferInfo.from_first);
955     }
956    
957     void Shiki_replace_buffer() {
958     static GtkWidget *find = NULL;
959     static GtkWidget *replace = NULL;
960     GtkWidget *dialog = gtk_dialog_new_with_buttons ("������������������", GTK_WINDOW(Shiki_EDITOR_WINDOW), GTK_DIALOG_DESTROY_WITH_PARENT, NULL);
961     GtkWidget *table = gtk_table_new(7, 3, FALSE);
962     GtkWidget *find_label = gtk_label_new("������ : ");
963     GtkWidget *rep_label = gtk_label_new("������ : ");
964     GtkWidget *check1 = gtk_check_button_new_with_label("���������������������������������");
965     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check1), TRUE);
966     GtkWidget *check2 = gtk_check_button_new_with_label("���������������������������");
967     GtkWidget *check3 = gtk_check_button_new_with_label("������������");
968     GtkWidget *check4 = gtk_check_button_new_with_label("���������������������������������������������");
969     GtkWidget *check5 = gtk_check_button_new_with_label("���������������������������");
970     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check5), TRUE);
971     GtkWidget *interactive = gtk_button_new_with_label ("������������");
972     g_signal_connect (interactive, "clicked", G_CALLBACK(replace_interactive_handler), NULL);
973     GtkWidget *all = gtk_button_new_with_label ("������������");
974     g_signal_connect (all, "clicked", G_CALLBACK(replace_all_handler), NULL);
975     GtkWidget *cancel = gtk_button_new_with_label ("���������������");
976    
977     if(!find && !replace) {
978     ShikiReplaceBufferInfo.find = find = g_object_ref(gtk_entry_new());
979     ShikiReplaceBufferInfo.replace = replace = g_object_ref(gtk_entry_new());
980     }
981 aloha 1.14
982 aloha 1.13 ShikiReplaceBufferInfo.ci =
983 aloha 1.14 ShikiReplaceBufferInfo.word =
984     ShikiReplaceBufferInfo.regexp =
985     ShikiReplaceBufferInfo.escape = FALSE;
986 aloha 1.13 ShikiReplaceBufferInfo.from_first = TRUE;
987    
988     g_signal_connect (check1, "toggled", G_CALLBACK (toggled_handler), &(ShikiReplaceBufferInfo.ci));
989     g_signal_connect (check2, "toggled", G_CALLBACK (toggled_handler), &(ShikiReplaceBufferInfo.word));
990     g_signal_connect (check3, "toggled", G_CALLBACK (toggled_handler), &(ShikiReplaceBufferInfo.regexp));
991     g_signal_connect (check4, "toggled", G_CALLBACK (toggled_handler), &(ShikiReplaceBufferInfo.escape));
992     g_signal_connect (check5, "toggled", G_CALLBACK (toggled_handler), &(ShikiReplaceBufferInfo.from_first));
993    
994     g_signal_connect (G_OBJECT(dialog), "delete_event", G_CALLBACK(gtk_widget_destroy), NULL);
995     g_signal_connect (G_OBJECT(cancel), "clicked", G_CALLBACK(destroy_handler), dialog);
996     gtk_table_set_row_spacings(GTK_TABLE(table), 10);
997     gtk_table_set_col_spacings(GTK_TABLE(table), 10);
998     gtk_container_border_width (GTK_CONTAINER (dialog), 10);
999    
1000     gtk_table_attach_defaults (GTK_TABLE(table), find_label, 0, 1, 0, 1);
1001     gtk_table_attach_defaults (GTK_TABLE(table), find, 1, 2, 0, 1);
1002     gtk_table_attach_defaults (GTK_TABLE(table), interactive, 2, 3, 0, 1);
1003    
1004     gtk_table_attach_defaults (GTK_TABLE(table), rep_label, 0, 1, 1, 2);
1005     gtk_table_attach_defaults (GTK_TABLE(table), replace, 1, 2, 1, 2);
1006     gtk_table_attach_defaults (GTK_TABLE(table), all, 2, 3, 1, 2);
1007    
1008     gtk_table_attach_defaults (GTK_TABLE(table), check1, 1, 2, 2, 3);
1009     gtk_table_attach_defaults (GTK_TABLE(table), cancel, 2, 3, 2, 3);
1010    
1011     gtk_table_attach_defaults (GTK_TABLE(table), check2, 1, 2, 3, 4);
1012     gtk_table_attach_defaults (GTK_TABLE(table), check3, 1, 2, 4, 5);
1013     gtk_table_attach_defaults (GTK_TABLE(table), check4, 1, 2, 5, 6);
1014     gtk_table_attach_defaults (GTK_TABLE(table), check5, 1, 2, 6, 7);
1015    
1016     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
1017     gtk_widget_show_all(table);
1018     gtk_dialog_run(GTK_DIALOG(dialog));
1019     }
1020    
1021    

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26