Develop and Download Open Source Software

Browse CVS Repository

Contents of /shiki/shiki/buffer.c

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


Revision 1.20 - (show annotations) (download) (as text)
Sun Feb 18 10:16:43 2007 UTC (17 years 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 /* 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 * $Id: buffer.c,v 1.19 2007/02/18 10:07:11 aloha Exp $
28 */
29 #include"shiki.h"
30
31 /* GtkTextBuffer ��������������������� ShikiBuffer ��������������������� */
32 static gint compBuffer(gconstpointer a, gconstpointer b) {
33 return ((ShikiBuffer *)a)->text_buffer == b ? 0 : b - a;
34 }
35
36 static GList *get_ShikiBufferListElement_By_GtkTextBuffer(GtkTextBuffer *b) {
37 return g_list_find_custom(Shiki_EDITOR_BUFFER_LIST, b, compBuffer);
38 }
39
40 /* ������������������������������������������������������������������������������������������ */
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
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 }
64
65 /* ������������������������������������������������ */
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
84 void Shiki_undo() {
85 GtkTextIter start, end;
86 ShikiUndoInfo *undoInfo;
87 GList *p;
88 if(!Shiki_CURRENT_UNDO_INFO_LIST) {
89 Shiki_msgbox("������������ Undo ���������������");
90 return;
91 }
92 undoInfo = Shiki_CURRENT_UNDO_INFO_LIST->data;
93 if(undoInfo->action == SHIKI_UNDO_UNDO) {
94 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 }
123
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 return;
172 }
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 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 p = Shiki_CURRENT_UNDO_INFO_LIST->prev;
191
192 if(undoInfo->action == SHIKI_UNDO_INSERT)
193 gtk_text_buffer_delete(Shiki_CURRENT_TEXT_BUFFER, &start, &end);
194 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 }
230
231 /* ��������������������������������������������������������������� */
232 void Shiki_update_modeline() {
233 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 }
246
247 static void cursor_moved_handler() {
248 Shiki_update_modeline();
249 }
250
251 /* ��������������������������������������� (������������) ��������� */
252 GtkTextBuffer *Shiki_new_buffer_create(gchar *filename) {
253
254 /*-------------------- ������������������������ ----------------------------------*/
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 //tabinfo->tabpage_label = g_strndup(tabinfo->name, 10);
262 tabinfo->env = Scm_MakeModule(NULL, FALSE);
263
264 /* ��������������������������������� */
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 tabinfo->tabpage_label = tabinfo->name;
283
284 /* ��������� GC ��������������������� */
285 Scm_Define(SCM_CURRENT_MODULE(), SCM_SYMBOL(SCM_INTERN(tabinfo->name)), tabinfo->env);
286
287 /* 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 g_signal_connect(tabinfo->text_buffer, "mark_set", G_CALLBACK(cursor_moved_handler), tabinfo->text_view);
302 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 /* ������/������������������������������������ */
314 gtk_text_buffer_create_tag(tabinfo->text_buffer, "match_highlighting", "background", "pink", NULL);
315
316 /* ������������������������������������������ */
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
334 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 return tabinfo->text_buffer;
337 }
338
339 void Shiki_create_file_buffer(const gchar *filename) {
340 gchar *text, *utf8filename = g_locale_to_utf8(filename, -1, NULL, NULL, NULL);
341 GtkTextIter p;
342 ScmEvalPacket packet;
343 gint result;
344
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 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
357 /* ������������������������������������������������������������������������������ */
358 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 gtk_text_buffer_set_text(Shiki_CURRENT_TEXT_BUFFER, text, -1);
362 } else {
363 /* 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 gtk_text_buffer_set_text(Shiki_CURRENT_TEXT_BUFFER, text, -1);
373 else
374 gtk_text_buffer_set_text(Shiki_CURRENT_TEXT_BUFFER, contents, -1);
375 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 Shiki_update_modeline(Shiki_CURRENT_TEXT_BUFFER);
385 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 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 /* g_print("%d page delete.\n", bufNum); */
403
404 g_print("buffer list length = %d\n", g_list_length(Shiki_EDITOR_BUFFER_LIST));
405 /* ��������� 1 ��������������������������������������������������� */
406 if(g_list_length(Shiki_EDITOR_BUFFER_LIST) == 1)
407 return;
408
409 /* Scheme ������������������������ */
410 Scm_Define(SCM_CURRENT_MODULE(), SCM_SYMBOL(SCM_INTERN(tabInfo->name)), SCM_FALSE);
411
412 /* ������������������������ */
413 g_hash_table_remove(Shiki_EDITOR_BUFNAME_HASH, tabInfo->name);
414 /* ��������������������������������������������������������������������������������������������� */
415 g_signal_handler_disconnect(Shiki_EDITOR_WINDOW, tabInfo->delete_handler_id);
416 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 /* double free bugs
421 g_free(tabInfo->tabpage_label);
422 g_free(tabInfo->name);
423 */
424 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 /* gtk_notebook_set_current_page(Shiki_EDITOR_NOTEBOOK, bufNum > 0 ? bufNum-1 : 0); */
430 }
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
460 return gtk_text_buffer_delete(Shiki_CURRENT_TEXT_BUFFER, &s, &e);
461 }
462 }
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
521 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
526 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 }
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 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 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
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 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
603 GTK_BUTTONS_YES_NO, msg);
604 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 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
616 GTK_BUTTONS_YES_NO, msg);
617 gint resp;
618 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_NO);
619 resp = gtk_dialog_run(GTK_DIALOG(dialog));
620 gtk_widget_destroy(dialog);
621 if(GTK_RESPONSE_YES == resp)
622 return TRUE;
623 return FALSE;
624 }
625
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
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
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 ScmEvalPacket packet;
731 /* ������������������������������ */
732 ScmObj os = Scm_MakeOutputStringPort(TRUE);
733 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 else
738 for(i = 0; i < packet.numResults; i++)
739 Scm_Printf(SCM_PORT(os), "%S\n", packet.results[i]);
740
741 msg = Scm_GetString(SCM_STRING(Scm_GetOutputString(SCM_PORT(os))));
742 /* ������������������ */
743 Scm_ClosePort(SCM_PORT(os));
744
745 return msg;
746 }
747
748 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
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
829 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 0.0, FALSE, FALSE, FALSE);
839 }
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
873 if(!input)
874 ShikiSearchBufferInfo.input = input = g_object_ref(gtk_entry_new());
875 ShikiSearchBufferInfo.ci =
876 ShikiSearchBufferInfo.word =
877 ShikiSearchBufferInfo.regexp =
878 ShikiSearchBufferInfo.escape =
879 ShikiSearchBufferInfo.loop = FALSE;
880
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 GTK_TEXT_SEARCH_TEXT_ONLY, &match_start, &match_end, &end))) {
930
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
982 ShikiReplaceBufferInfo.ci =
983 ShikiReplaceBufferInfo.word =
984 ShikiReplaceBufferInfo.regexp =
985 ShikiReplaceBufferInfo.escape = FALSE;
986 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