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.9 - (show annotations) (download) (as text)
Wed Nov 29 04:37:23 2006 UTC (17 years, 4 months ago) by aloha
Branch: MAIN
Changes since 1.8: +145 -3 lines
File MIME type: text/x-csrc
bug fix (C-x C-s) and add no-or-yes-p API

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.8 2006/11/28 16:29:22 aloha Exp $
28 */
29 #include"shiki.h"
30
31 ScmClass *ShikiBufferClass;
32 extern void Scm_Init_xyzzylisp(ScmModule *module);
33
34 /* GtkTextBuffer ��������������������� ShikiBuffer ��������������������� */
35 static gint compBuffer(gconstpointer a, gconstpointer b) {
36 return ((ShikiBuffer *)a)->text_buffer == b ? 0 : b - a;
37 }
38
39 static GList *get_ShikiBufferListElement_By_GtkTextBuffer(GtkTextBuffer *b) {
40 return g_list_find_custom(Shiki_EDITOR_BUFFER_LIST, b, compBuffer);
41 }
42
43 static void buffer_print(ScmObj obj, ScmPort *out, ScmWriteContext *ctx) {
44 GtkTextBuffer *b = SHIKI_BUFFER_UNBOX(obj);
45 GList *l = g_list_find_custom(Shiki_EDITOR_BUFFER_LIST, b, compBuffer);
46 if(l)
47 Scm_Printf(out, "#<buffer: %s>", ((ShikiBuffer *)(l->data))->name);
48 else
49 Scm_Printf(out, "#<deleted buffer: %p>", b);
50 }
51
52 static void buffer_cleanup(ScmObj obj)
53 {
54 g_object_unref(SHIKI_BUFFER_UNBOX(obj));
55 }
56
57 /* ������������������������������������������������������������������������������������������ */
58 static gboolean delete_event_handler(GtkWidget *widget, GdkEvent *event, GtkTextBuffer *buffer){
59 /* delete-event ������������������������FALSE ��������������������������������������������� */
60 return Shiki_need_buffer_save_p(buffer) && !Shiki_yes_or_no_p("��������������������������������������������������������������������������� ?");
61 }
62
63 /* ��������������������������������������������� */
64 static void insert_text_handler(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *str, gint len) {
65 /* Undo ��������������������������� */
66 ShikiUndoInfo *undoInfo = g_malloc(sizeof(ShikiUndoInfo));
67 g_return_if_fail(undoInfo != NULL);
68 undoInfo->action = SHIKI_UNDO_INSERT;
69 undoInfo->str = g_strdup(str);
70 undoInfo->strlen = len;
71 undoInfo->start = gtk_text_iter_get_offset(iter);
72 undoInfo->end = undoInfo->start + undoInfo->strlen;
73 Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo);
74 }
75
76 /* ��������������������������������������������������������������� */
77 static void update_modeline_label() {
78 static gchar label[1024];
79 GtkTextIter p;
80 gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
81
82 g_snprintf(label, 1024, "--%s- %-10s (Gauche Interaction) [%s] L%d:%d ",
83 gtk_text_buffer_get_modified(Shiki_CURRENT_TEXT_BUFFER) ? "**" : "--",
84 Shiki_CURRENT_BASENAME,
85 Shiki_CURRENT_CES,
86 gtk_text_iter_get_line(&p) + 1,
87 gtk_text_iter_get_line_offset (&p) + 1);
88 gtk_label_set_text(GTK_LABEL(Shiki_EDITOR_MODELINE_LABEL), label);
89 }
90
91 /* ������������������������������������������������ */
92 static void delete_range_handler(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end) {
93 /* Undo ��������������������������� */
94 ShikiUndoInfo *undoInfo = g_malloc(sizeof(ShikiUndoInfo));
95 g_return_if_fail(undoInfo != NULL);
96 undoInfo->action = SHIKI_UNDO_DELETE;
97 undoInfo->str = gtk_text_buffer_get_text(buffer, start, end, FALSE);
98 undoInfo->start = gtk_text_iter_get_offset(start);
99 undoInfo->end = gtk_text_iter_get_offset(end);
100 undoInfo->strlen = end - start;
101 Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo);
102 }
103
104 /* ��������������������������������������� (������������) ��������� */
105 GtkTextBuffer *Shiki_new_buffer_create(gchar *filename) {
106 /*-------------------- ������������������������ ----------------------------------*/
107 /* ShikiBuffer ������������������������������������������������������������������ */
108 ShikiBuffer *tabinfo = g_malloc(sizeof(ShikiBuffer));
109 tabinfo->locale = "Gtk Default (utf8)";
110 tabinfo->undoInfoList = NULL;
111 tabinfo->filename = filename;
112 tabinfo->name = g_path_get_basename(filename);
113 tabinfo->tabpage_label = g_strndup(tabinfo->name, 7);
114 tabinfo->env = Scm_MakeModule(NULL, FALSE);
115
116 ShikiBufferClass = Scm_MakeForeignPointerClass(SCM_MODULE(tabinfo->env),
117 "<buffer>", buffer_print, buffer_cleanup,
118 SCM_FOREIGN_POINTER_KEEP_IDENTITY
119 |
120 SCM_FOREIGN_POINTER_MAP_NULL);
121
122 /* xyzzy lisp ��������������� */
123 Scm_Init_xyzzylisp(SCM_MODULE(tabinfo->env));
124
125 /* ������������������������������ (������������������������) ��������� */
126 tabinfo->tabpage = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
127 gtk_scrolled_window_set_policy (tabinfo->tabpage, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
128
129 /* ��������������������������������������������������������������������������������������� */
130 tabinfo->text_view = GTK_TEXT_VIEW(gtk_text_view_new());
131 gtk_text_view_set_wrap_mode(tabinfo->text_view, GTK_WRAP_WORD);
132 tabinfo->text_buffer = gtk_text_view_get_buffer(tabinfo->text_view);
133 gtk_widget_set_size_request(GTK_WIDGET(tabinfo->text_view), 680, 700);
134
135 gtk_container_add(GTK_CONTAINER(tabinfo->tabpage), GTK_WIDGET(tabinfo->text_view));
136 g_signal_connect(tabinfo->text_buffer, "mark_set", G_CALLBACK(update_modeline_label), tabinfo->text_view);
137 g_signal_connect(tabinfo->text_buffer, "insert-text", G_CALLBACK(insert_text_handler), NULL);
138 g_signal_connect(tabinfo->text_buffer, "delete-range", G_CALLBACK(delete_range_handler), NULL);
139
140 /* ������������������������������������������������������������������������������������������������������ */
141 tabinfo->delete_handler_id = g_signal_connect(Shiki_EDITOR_WINDOW, "delete_event", G_CALLBACK(delete_event_handler), tabinfo->text_buffer);
142
143 /* ������������������������ */
144
145 /* ������������������������������������������������ */
146 gtk_text_buffer_create_tag(tabinfo->text_buffer, "parent_emphasis_background", "background", "green", NULL);
147
148 /* ������������������������������������������ */
149 gtk_text_buffer_create_tag(tabinfo->text_buffer, "keyword_highlighting", "foreground", "blue", NULL);
150 /* ������ */
151 gtk_text_buffer_create_tag(tabinfo->text_buffer, "function_highlighting", "foreground", "red", NULL);
152 /* ������������ */
153 gtk_text_buffer_create_tag (tabinfo->text_buffer, "comment_highlighting", "foreground", "purple", NULL);
154 /* ��������� */
155 gtk_text_buffer_create_tag (tabinfo->text_buffer, "string_highlighting", "foreground", "orange", NULL);
156 /* ������������������������������������������ */
157 gtk_notebook_append_page(Shiki_EDITOR_NOTEBOOK, GTK_WIDGET(tabinfo->tabpage), gtk_label_new(tabinfo->tabpage_label));
158 /* ������������������������������������������������������������������ */
159 Shiki_EDITOR_BUFFER_LIST = g_list_append(Shiki_EDITOR_BUFFER_LIST, tabinfo);
160
161 gtk_widget_show_all(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK));
162 /* ��������������������������������� */
163 gtk_notebook_set_current_page(Shiki_EDITOR_NOTEBOOK, g_list_length(Shiki_EDITOR_BUFFER_LIST) - 1);
164 //Shiki_CURRENT_TAB_INFO = tabinfo;
165 return tabinfo->text_buffer;
166 }
167
168 void Shiki_delete_buffer(GtkTextBuffer *buffer) {
169 /* ��������������������������������������������������������������������������������������������������� */
170 /* ���������������������Scheme ������������������������ Gtk ������������������������������������������������ */
171 GList *bufListElem = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
172 ShikiBuffer *tabInfo = bufListElem->data;
173 gint bufNum = g_list_position(Shiki_EDITOR_BUFFER_LIST, bufListElem);
174
175 /* ��������� 1 ��������������������������������������������������� */
176 if(g_list_length(Shiki_EDITOR_BUFFER_LIST) == 1)
177 return;
178 /* ��������������������������������������������������������������������������������������������� */
179 g_signal_handler_disconnect(Shiki_EDITOR_WINDOW, tabInfo->delete_handler_id);
180 Shiki_EDITOR_BUFFER_LIST = g_list_delete_link(Shiki_EDITOR_BUFFER_LIST, bufListElem);
181 gtk_widget_destroy(GTK_WIDGET(tabInfo->tabpage));
182 g_free(tabInfo->tabpage_label);
183 g_free(tabInfo->name);
184 g_free(tabInfo->filename);
185 g_free(tabInfo);
186 gtk_notebook_remove_page(Shiki_EDITOR_NOTEBOOK, bufNum);
187 /* ��������������� */
188 gtk_widget_queue_draw(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK));
189 }
190
191 GtkTextBuffer *Shiki_find_buffer(const gchar *name) {
192 GList *l;
193 for(l = Shiki_EDITOR_BUFFER_LIST; l != NULL; l = l->next)
194 if(strcmp(((ShikiBuffer *)l->data)->name, name) == 0)
195 return ((ShikiBuffer *)l->data)->text_buffer;
196 return NULL;
197 }
198
199 gchar *Shiki_buffer_substring(gint start, gint end) {
200 if(start >= end)
201 return NULL;
202 else {
203 GtkTextIter s, e;
204 gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &s, start);
205 gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &e, end);
206
207 return gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &s, &e, FALSE);
208 }
209 }
210
211 void Shiki_delete_region(gint start, gint end) {
212 if(start >= end)
213 return;
214 else {
215 GtkTextIter s, e;
216 gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &s, start);
217 gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &e, end);
218
219 return gtk_text_buffer_delete(Shiki_CURRENT_TEXT_BUFFER, &s, &e);
220 }
221 }
222
223 gint Shiki_point() {
224 GtkTextIter p;
225 gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
226 return gtk_text_iter_get_offset(&p);
227 }
228
229 gint Shiki_point_max() {
230 GtkTextIter p;
231 gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &p);
232 return gtk_text_iter_get_offset(&p);
233 }
234
235 gint Shiki_point_min() {
236 return 0;
237 }
238
239 void Shiki_goto_char(gint offset) {
240 GtkTextIter p;
241 gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &p, offset);
242 gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
243 }
244
245 void Shiki_forward_char() {
246 GtkTextIter p;
247 gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
248 gtk_text_iter_forward_char(&p);
249 gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
250 }
251
252 void Shiki_backward_char() {
253 GtkTextIter p;
254 gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
255 gtk_text_iter_backward_char(&p);
256 gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
257 }
258
259 void Shiki_goto_line(gint line) {
260 GtkTextIter p;
261 gtk_text_buffer_get_iter_at_line(Shiki_CURRENT_TEXT_BUFFER, &p, line);
262 gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
263 }
264
265 void Shiki_goto_bol() {
266 GtkTextIter p;
267 gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
268 gtk_text_buffer_get_iter_at_line_offset(Shiki_CURRENT_TEXT_BUFFER, &p, gtk_text_iter_get_line(&p), 0);
269 gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
270 }
271
272 void Shiki_goto_eol() {
273 GtkTextIter p;
274 gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
275 gtk_text_iter_forward_to_line_end(&p);
276 gtk_text_iter_backward_char(&p);
277 gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
278 }
279
280 void Shiki_forward_line(gint count) {
281 GtkTextIter p;
282 gint i;
283 gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER));
284
285 if(count >= 0) {
286 for(i = count; i != 0; i--)
287 gtk_text_view_forward_display_line(Shiki_CURRENT_TEXT_VIEW, &p);
288 } else {
289 for(i = count; i != 0; i++)
290 gtk_text_view_backward_display_line(Shiki_CURRENT_TEXT_VIEW, &p);
291 }
292 gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p);
293 }
294
295 const char *Shiki_buffer_name(GtkTextBuffer *buffer) {
296 GList *l = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
297 if(l)
298 return ((ShikiBuffer *)(l->data))->name;
299 else
300 return NULL;
301 }
302
303 gboolean Shiki_deleted_buffer_p(GtkTextBuffer *buffer) {
304 GList *l = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
305 if(l)
306 return FALSE;
307 else
308 return TRUE;
309 }
310
311 GtkTextBuffer *Shiki_get_next_buffer(GtkTextBuffer *buffer) {
312 GList *l = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
313 if(l && l->next)
314 return ((ShikiBuffer *)(l->next->data))->text_buffer;
315 else
316 return NULL;
317 }
318
319 GtkTextBuffer *Shiki_get_previous_buffer(GtkTextBuffer *buffer) {
320 GList *l = get_ShikiBufferListElement_By_GtkTextBuffer(buffer);
321 if(l && l->prev)
322 return ((ShikiBuffer *)(l->prev->data))->text_buffer;
323 else
324 return NULL;
325 }
326
327 ScmObj Shiki_buffer_list() {
328 GList *l;
329 GtkTextBuffer *b;
330 ScmObj bl = SCM_NIL;
331
332 for(l = Shiki_EDITOR_BUFFER_LIST; l != NULL; l = l->next) {
333 b= ((ShikiBuffer *)(l->data))->text_buffer;
334 bl = Scm_Cons(SHIKI_BUFFER_BOX(g_object_ref(b)), bl);
335 }
336 return bl;
337 }
338
339 void Shiki_erase_buffer(GtkTextBuffer *buffer) {
340 GtkTextIter start, end;
341 gtk_text_buffer_get_start_iter(buffer, &start);
342 gtk_text_buffer_get_end_iter(buffer, &end);
343 gtk_text_buffer_delete(buffer, &start, &end);
344 }
345
346 const gchar *Shiki_file_name_dialog(const gchar *msg) {
347
348 GtkWidget *dialog = gtk_file_selection_new(msg);
349 gint resp = gtk_dialog_run(GTK_DIALOG(dialog));
350 const gchar *filename = NULL;
351
352 if(resp == GTK_RESPONSE_OK)
353 filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dialog));
354
355 gtk_widget_destroy(dialog);
356 return filename;
357 }
358
359 gboolean Shiki_yes_or_no_p(const gchar *msg) {
360 GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(Shiki_EDITOR_WINDOW),
361 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
362 GTK_BUTTONS_YES_NO, msg);
363 gint resp;
364 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
365 resp = gtk_dialog_run(GTK_DIALOG(dialog));
366 gtk_widget_destroy(dialog);
367 if(GTK_RESPONSE_YES == resp)
368 return TRUE;
369 return FALSE;
370 }
371
372 gboolean Shiki_no_or_yes_p(const gchar *msg) {
373 GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(Shiki_EDITOR_WINDOW),
374 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
375 GTK_BUTTONS_YES_NO, msg);
376 gint resp;
377 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_NO);
378 resp = gtk_dialog_run(GTK_DIALOG(dialog));
379 gtk_widget_destroy(dialog);
380 if(GTK_RESPONSE_YES == resp)
381 return TRUE;
382 return FALSE;
383 }
384
385 gboolean Shiki_need_buffer_save_p(GtkTextBuffer *buffer) {
386 return gtk_text_buffer_get_modified(buffer);
387 }
388
389 /* ������������ */
390 void Shiki_kill_buffer(GtkTextBuffer *buffer) {
391 if(!Shiki_need_buffer_save_p(buffer) || Shiki_yes_or_no_p("��������������������������������������������������������������������������� ?"))
392 Shiki_delete_buffer(buffer);
393 }

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