2 * GNT - The GLib Ncurses Toolkit
4 * GNT is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * This library is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
24 #include "gnttextview.h"
38 GntTextFormatFlags tvflag
;
41 int end
; /* This is the next byte of the last character of this segment */
46 GList
*segments
; /* A list of GntTextSegments */
47 int length
; /* The current length of the line so far (ie. onscreen width) */
48 gboolean soft
; /* TRUE if it's an overflow from prev. line */
58 static GntWidgetClass
*parent_class
= NULL
;
60 static gchar
*select_start
;
61 static gchar
*select_end
;
62 static gboolean double_click
;
64 static void reset_text_view(GntTextView
*view
);
67 gnt_text_view_draw(GntWidget
*widget
)
69 GntTextView
*view
= GNT_TEXT_VIEW(widget
);
73 int comp
= 0; /* Used for top-aligned text */
74 gboolean has_scroll
= !(view
->flags
& GNT_TEXT_VIEW_NO_SCROLL
);
76 wbkgd(widget
->window
, gnt_color_pair(GNT_COLOR_NORMAL
));
77 werase(widget
->window
);
79 if ((view
->flags
& GNT_TEXT_VIEW_TOP_ALIGN
) &&
80 g_list_length(view
->list
) < widget
->priv
.height
) {
81 GList
*now
= view
->list
;
82 comp
= widget
->priv
.height
- g_list_length(view
->list
);
83 view
->list
= g_list_nth_prev(view
->list
, comp
);
85 view
->list
= g_list_first(now
);
86 comp
= widget
->priv
.height
- g_list_length(view
->list
);
92 for (i
= 0, lines
= view
->list
; i
< widget
->priv
.height
&& lines
; i
++, lines
= lines
->next
)
95 GntTextLine
*line
= lines
->data
;
97 wmove(widget
->window
, widget
->priv
.height
- 1 - i
- comp
, 0);
99 for (iter
= line
->segments
; iter
; iter
= iter
->next
)
101 GntTextSegment
*seg
= iter
->data
;
102 char *end
= view
->string
->str
+ seg
->end
;
104 chtype fl
= seg
->flags
;
106 if (select_start
< view
->string
->str
+ seg
->start
&& select_end
> view
->string
->str
+ seg
->end
) {
108 wattrset(widget
->window
, fl
);
109 wprintw(widget
->window
, "%s", (view
->string
->str
+ seg
->start
));
110 } else if (select_start
&& select_end
&&
111 ((select_start
>= view
->string
->str
+ seg
->start
&& select_start
<= view
->string
->str
+ seg
->end
) ||
112 (select_end
<= view
->string
->str
+ seg
->end
&& select_start
<= view
->string
->str
+ seg
->start
))) {
113 char *cur
= view
->string
->str
+ seg
->start
;
114 while (*cur
!= '\0') {
115 gchar
*last
= g_utf8_next_char(cur
);
117 if (cur
>= select_start
&& cur
<= select_end
)
121 str
= g_strndup(cur
, last
- cur
);
122 wattrset(widget
->window
, fl
);
123 waddstr(widget
->window
, str
);
125 cur
= g_utf8_next_char(cur
);
128 wattrset(widget
->window
, fl
);
129 wprintw(widget
->window
, "%s", (view
->string
->str
+ seg
->start
));
133 wattroff(widget
->window
, A_UNDERLINE
| A_BLINK
| A_REVERSE
);
134 whline(widget
->window
, ' ', widget
->priv
.width
- line
->length
- has_scroll
);
137 scrcol
= widget
->priv
.width
- 1;
138 rows
= widget
->priv
.height
- 2;
139 if (has_scroll
&& rows
> 0)
141 int total
= g_list_length(g_list_first(view
->list
));
142 int showing
, position
, up
, down
;
144 showing
= rows
* rows
/ total
+ 1;
145 showing
= MIN(rows
, showing
);
148 up
= g_list_length(lines
);
151 position
= (rows
- showing
) * up
/ MAX(1, up
+ down
);
152 position
= MAX((lines
!= NULL
), position
);
154 if (showing
+ position
> rows
)
155 position
= rows
- showing
;
157 if (showing
+ position
== rows
&& view
->list
&& view
->list
->prev
)
158 position
= MAX(1, rows
- 1 - showing
);
159 else if (showing
+ position
< rows
&& view
->list
&& !view
->list
->prev
)
160 position
= rows
- showing
;
162 mvwvline(widget
->window
, position
+ 1, scrcol
,
163 ACS_CKBOARD
| gnt_color_pair(GNT_COLOR_HIGHLIGHT_D
), showing
);
167 mvwaddch(widget
->window
, 0, scrcol
,
168 (lines
? ACS_UARROW
: ' ') | gnt_color_pair(GNT_COLOR_HIGHLIGHT_D
));
169 mvwaddch(widget
->window
, widget
->priv
.height
- 1, scrcol
,
170 ((view
->list
&& view
->list
->prev
) ? ACS_DARROW
: ' ') |
171 gnt_color_pair(GNT_COLOR_HIGHLIGHT_D
));
178 gnt_text_view_size_request(GntWidget
*widget
)
180 if (!GNT_WIDGET_IS_FLAG_SET(widget
, GNT_WIDGET_MAPPED
))
182 gnt_widget_set_size(widget
, 64, 20);
187 gnt_text_view_map(GntWidget
*widget
)
189 if (widget
->priv
.width
== 0 || widget
->priv
.height
== 0)
190 gnt_widget_size_request(widget
);
195 gnt_text_view_key_pressed(GntWidget
*widget
, const char *text
)
201 free_text_segment(gpointer data
, gpointer null
)
203 GntTextSegment
*seg
= data
;
208 free_text_line(gpointer data
, gpointer null
)
210 GntTextLine
*line
= data
;
211 g_list_foreach(line
->segments
, free_text_segment
, NULL
);
212 g_list_free(line
->segments
);
217 free_tag(gpointer data
, gpointer null
)
219 GntTextTag
*tag
= data
;
225 gnt_text_view_destroy(GntWidget
*widget
)
227 GntTextView
*view
= GNT_TEXT_VIEW(widget
);
228 view
->list
= g_list_first(view
->list
);
229 g_list_foreach(view
->list
, free_text_line
, NULL
);
230 g_list_free(view
->list
);
231 g_list_foreach(view
->tags
, free_tag
, NULL
);
232 g_list_free(view
->tags
);
233 g_string_free(view
->string
, TRUE
);
237 gnt_text_view_get_p(GntTextView
*view
, int x
, int y
)
240 GntWidget
*wid
= GNT_WIDGET(view
);
247 y
= wid
->priv
.height
- y
;
248 if (g_list_length(view
->list
) < y
) {
250 y
= g_list_length(view
->list
) - 1;
253 lines
= g_list_nth(view
->list
, y
- 1);
259 } while (line
&& !line
->segments
&& lines
);
261 if (!line
|| !line
->segments
) /* no valid line */
263 segs
= line
->segments
;
264 seg
= (GntTextSegment
*)segs
->data
;
265 pos
= view
->string
->str
+ seg
->start
;
266 x
= MIN(x
, line
->length
);
269 pos
= g_utf8_next_char(pos
);
270 u
= g_utf8_to_ucs4(pos
, -1, NULL
, NULL
, NULL
);
271 if (u
&& g_unichar_iswide(*u
))
279 select_word_text(GntTextView
*view
, gchar
*c
)
284 while ((t
= g_utf8_prev_char(start
))) {
285 if (!g_ascii_isspace(*t
)) {
286 if (start
== view
->string
->str
)
292 while ((t
= g_utf8_next_char(end
))) {
293 if (!g_ascii_isspace(*t
))
298 select_start
= start
;
300 endsize
= g_utf8_next_char(select_end
); /* End at the correct byte */
301 return g_string_new_len(start
, endsize
- start
);
304 static gboolean
too_slow(gpointer n
)
306 double_click
= FALSE
;
311 gnt_text_view_clicked(GntWidget
*widget
, GntMouseEvent event
, int x
, int y
)
313 if (event
== GNT_MOUSE_SCROLL_UP
) {
314 gnt_text_view_scroll(GNT_TEXT_VIEW(widget
), -1);
315 } else if (event
== GNT_MOUSE_SCROLL_DOWN
) {
316 gnt_text_view_scroll(GNT_TEXT_VIEW(widget
), 1);
317 } else if (event
== GNT_LEFT_MOUSE_DOWN
) {
318 select_start
= gnt_text_view_get_p(GNT_TEXT_VIEW(widget
), x
- widget
->priv
.x
, y
- widget
->priv
.y
);
319 g_timeout_add(500, too_slow
, NULL
);
320 } else if (event
== GNT_MOUSE_UP
) {
323 select_end
= gnt_text_view_get_p(GNT_TEXT_VIEW(widget
), x
- widget
->priv
.x
, y
- widget
->priv
.y
);
324 if (select_end
< select_start
) {
325 gchar
*t
= select_start
;
326 select_start
= select_end
;
329 if (select_start
== select_end
) {
331 clip
= select_word_text(GNT_TEXT_VIEW(widget
), select_start
);
332 double_click
= FALSE
;
337 gnt_widget_draw(widget
);
341 gchar
*endsize
= g_utf8_next_char(select_end
); /* End at the correct byte */
342 clip
= g_string_new_len(select_start
, endsize
- select_start
);
344 gnt_widget_draw(widget
);
345 gnt_set_clipboard_string(clip
->str
);
346 g_string_free(clip
, TRUE
);
354 gnt_text_view_reflow(GntTextView
*view
)
356 /* This is pretty ugly, and inefficient. Someone do something about it. */
358 GList
*back
, *iter
, *list
;
360 int pos
= 0; /* no. of 'real' lines */
370 back
= g_list_last(view
->list
);
373 string
= view
->string
;
375 reset_text_view(view
);
377 view
->string
= g_string_set_size(view
->string
, string
->len
);
378 view
->string
->len
= 0;
379 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(view
), GNT_WIDGET_DRAWING
);
381 for (; back
; back
= back
->prev
) {
383 if (back
->next
&& !line
->soft
) {
384 gnt_text_view_append_text_with_flags(view
, "\n", GNT_TEXT_FLAG_NORMAL
);
387 for (iter
= line
->segments
; iter
; iter
= iter
->next
) {
388 GntTextSegment
*seg
= iter
->data
;
389 char *start
= string
->str
+ seg
->start
;
390 char *end
= string
->str
+ seg
->end
;
393 gnt_text_view_append_text_with_flags(view
, start
, seg
->tvflag
);
396 free_text_line(line
, NULL
);
400 list
= view
->list
= g_list_first(view
->list
);
401 /* Go back to the line that was in view before resizing started */
403 while (((GntTextLine
*)list
->data
)->soft
)
408 GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(view
), GNT_WIDGET_DRAWING
);
409 if (GNT_WIDGET(view
)->window
)
410 gnt_widget_draw(GNT_WIDGET(view
));
411 g_string_free(string
, TRUE
);
415 gnt_text_view_size_changed(GntWidget
*widget
, int w
, int h
)
417 if (w
!= widget
->priv
.width
&& GNT_WIDGET_IS_FLAG_SET(widget
, GNT_WIDGET_MAPPED
)) {
418 gnt_text_view_reflow(GNT_TEXT_VIEW(widget
));
423 gnt_text_view_class_init(GntTextViewClass
*klass
)
425 parent_class
= GNT_WIDGET_CLASS(klass
);
426 parent_class
->destroy
= gnt_text_view_destroy
;
427 parent_class
->draw
= gnt_text_view_draw
;
428 parent_class
->map
= gnt_text_view_map
;
429 parent_class
->size_request
= gnt_text_view_size_request
;
430 parent_class
->key_pressed
= gnt_text_view_key_pressed
;
431 parent_class
->clicked
= gnt_text_view_clicked
;
432 parent_class
->size_changed
= gnt_text_view_size_changed
;
438 gnt_text_view_init(GTypeInstance
*instance
, gpointer
class)
440 GntWidget
*widget
= GNT_WIDGET(instance
);
441 GntTextView
*view
= GNT_TEXT_VIEW(widget
);
442 GntTextLine
*line
= g_new0(GntTextLine
, 1);
444 GNT_WIDGET_SET_FLAGS(widget
, GNT_WIDGET_NO_BORDER
| GNT_WIDGET_NO_SHADOW
|
445 GNT_WIDGET_GROW_Y
| GNT_WIDGET_GROW_X
);
446 widget
->priv
.minw
= 5;
447 widget
->priv
.minh
= 2;
448 view
->string
= g_string_new(NULL
);
449 view
->list
= g_list_append(view
->list
, line
);
454 /******************************************************************************
456 *****************************************************************************/
458 gnt_text_view_get_gtype(void)
460 static GType type
= 0;
464 static const GTypeInfo info
= {
465 sizeof(GntTextViewClass
),
466 NULL
, /* base_init */
467 NULL
, /* base_finalize */
468 (GClassInitFunc
)gnt_text_view_class_init
,
469 NULL
, /* class_finalize */
470 NULL
, /* class_data */
473 gnt_text_view_init
, /* instance_init */
474 NULL
/* value_table */
477 type
= g_type_register_static(GNT_TYPE_WIDGET
,
485 GntWidget
*gnt_text_view_new()
487 GntWidget
*widget
= g_object_new(GNT_TYPE_TEXT_VIEW
, NULL
);
492 void gnt_text_view_append_text_with_flags(GntTextView
*view
, const char *text
, GntTextFormatFlags flags
)
494 gnt_text_view_append_text_with_tag(view
, text
, flags
, NULL
);
497 void gnt_text_view_append_text_with_tag(GntTextView
*view
, const char *text
,
498 GntTextFormatFlags flags
, const char *tagname
)
500 GntWidget
*widget
= GNT_WIDGET(view
);
502 const char *start
, *end
;
503 GList
*list
= view
->list
;
506 gboolean has_scroll
= !(view
->flags
& GNT_TEXT_VIEW_NO_SCROLL
);
507 gboolean wrap_word
= !(view
->flags
& GNT_TEXT_VIEW_WRAP_CHAR
);
509 if (text
== NULL
|| *text
== '\0')
512 fl
= gnt_text_format_flag_to_chtype(flags
);
514 len
= view
->string
->len
;
515 view
->string
= g_string_append(view
->string
, text
);
518 GntTextTag
*tag
= g_new0(GntTextTag
, 1);
519 tag
->name
= g_strdup(tagname
);
521 tag
->end
= view
->string
->len
;
522 view
->tags
= g_list_append(view
->tags
, tag
);
525 view
->list
= g_list_first(view
->list
);
527 start
= end
= view
->string
->str
+ len
;
531 GntTextSegment
*seg
= NULL
;
533 if (*end
== '\n' || *end
== '\r') {
534 if (!strncmp(end
, "\r\n", 2))
538 gnt_text_view_next_line(view
);
539 view
->list
= g_list_first(view
->list
);
543 line
= view
->list
->data
;
544 if (line
->length
== widget
->priv
.width
- has_scroll
) {
545 /* The last added line was exactly the same width as the widget */
546 line
= g_new0(GntTextLine
, 1);
548 view
->list
= g_list_prepend(view
->list
, line
);
551 if ((end
= strchr(start
, '\r')) != NULL
||
552 (end
= strchr(start
, '\n')) != NULL
) {
553 len
= gnt_util_onscreen_width(start
, end
- has_scroll
);
554 if (widget
->priv
.width
> 0 &&
555 len
>= widget
->priv
.width
- line
->length
- has_scroll
) {
561 end
= gnt_util_onscreen_width_to_pointer(start
,
562 widget
->priv
.width
- line
->length
- has_scroll
, &len
);
564 /* Try to append to the previous segment if possible */
565 if (line
->segments
) {
566 seg
= g_list_last(line
->segments
)->data
;
567 if (seg
->flags
!= fl
)
572 seg
= g_new0(GntTextSegment
, 1);
573 seg
->start
= start
- view
->string
->str
;
576 line
->segments
= g_list_append(line
->segments
, seg
);
580 if (wrap_word
&& *end
&& *end
!= '\n' && *end
!= '\r') {
581 const char *tmp
= end
;
582 while (end
&& *end
!= '\n' && *end
!= '\r' && !g_ascii_isspace(*end
)) {
583 end
= g_utf8_find_prev_char(seg
->start
+ view
->string
->str
, end
);
585 if (!end
|| !g_ascii_isspace(*end
))
588 end
++; /* Remove the space */
590 line
= g_new0(GntTextLine
, 1);
592 view
->list
= g_list_prepend(view
->list
, line
);
594 seg
->end
= end
- view
->string
->str
;
601 gnt_widget_draw(widget
);
604 void gnt_text_view_scroll(GntTextView
*view
, int scroll
)
608 view
->list
= g_list_first(view
->list
);
612 GList
*list
= g_list_nth_prev(view
->list
, scroll
);
614 list
= g_list_first(view
->list
);
619 GList
*list
= g_list_nth(view
->list
, -scroll
);
621 list
= g_list_last(view
->list
);
625 gnt_widget_draw(GNT_WIDGET(view
));
628 void gnt_text_view_next_line(GntTextView
*view
)
630 GntTextLine
*line
= g_new0(GntTextLine
, 1);
631 GList
*list
= view
->list
;
633 view
->list
= g_list_prepend(g_list_first(view
->list
), line
);
635 gnt_widget_draw(GNT_WIDGET(view
));
638 chtype
gnt_text_format_flag_to_chtype(GntTextFormatFlags flags
)
642 if (flags
& GNT_TEXT_FLAG_BOLD
)
644 if (flags
& GNT_TEXT_FLAG_UNDERLINE
)
646 if (flags
& GNT_TEXT_FLAG_BLINK
)
649 if (flags
& GNT_TEXT_FLAG_DIM
)
650 fl
|= (A_DIM
| gnt_color_pair(GNT_COLOR_DISABLED
));
651 else if (flags
& GNT_TEXT_FLAG_HIGHLIGHT
)
652 fl
|= (A_DIM
| gnt_color_pair(GNT_COLOR_HIGHLIGHT
));
653 else if ((flags
& A_COLOR
) == 0)
654 fl
|= gnt_color_pair(GNT_COLOR_NORMAL
);
656 fl
|= (flags
& A_COLOR
);
661 static void reset_text_view(GntTextView
*view
)
665 g_list_foreach(view
->list
, free_text_line
, NULL
);
666 g_list_free(view
->list
);
669 line
= g_new0(GntTextLine
, 1);
670 view
->list
= g_list_append(view
->list
, line
);
672 g_string_free(view
->string
, TRUE
);
673 view
->string
= g_string_new(NULL
);
676 void gnt_text_view_clear(GntTextView
*view
)
678 reset_text_view(view
);
680 g_list_foreach(view
->tags
, free_tag
, NULL
);
683 if (GNT_WIDGET(view
)->window
)
684 gnt_widget_draw(GNT_WIDGET(view
));
687 int gnt_text_view_get_lines_below(GntTextView
*view
)
690 GList
*list
= view
->list
;
691 while ((list
= list
->prev
))
696 int gnt_text_view_get_lines_above(GntTextView
*view
)
699 GList
*list
= view
->list
;
700 list
= g_list_nth(view
->list
, GNT_WIDGET(view
)->priv
.height
);
703 while ((list
= list
->next
))
709 * XXX: There are quite possibly more than a few bugs here.
711 int gnt_text_view_tag_change(GntTextView
*view
, const char *name
, const char *text
, gboolean all
)
713 GList
*alllines
= g_list_first(view
->list
);
714 GList
*list
, *next
, *iter
, *inext
;
715 const int text_length
= text
? strlen(text
) : 0;
717 for (list
= view
->tags
; list
; list
= next
) {
718 GntTextTag
*tag
= list
->data
;
720 if (strcmp(tag
->name
, name
) == 0) {
722 char *before
, *after
;
726 before
= g_strndup(view
->string
->str
, tag
->start
);
727 after
= g_strdup(view
->string
->str
+ tag
->end
);
728 change
= (tag
->end
- tag
->start
) - text_length
;
730 g_string_printf(view
->string
, "%s%s%s", before
, text
? text
: "", after
);
734 /* Update the offsets of the next tags */
735 for (iter
= next
; iter
; iter
= iter
->next
) {
736 GntTextTag
*t
= iter
->data
;
741 /* Update the offsets of the segments */
742 for (iter
= alllines
; iter
; iter
= inext
) {
744 GntTextLine
*line
= iter
->data
;
746 for (segs
= line
->segments
; segs
; segs
= snext
) {
747 GntTextSegment
*seg
= segs
->data
;
749 if (seg
->start
>= tag
->end
) {
750 /* The segment is somewhere after the tag */
751 seg
->start
-= change
;
753 } else if (seg
->end
<= tag
->start
) {
754 /* This segment is somewhere in front of the tag */
755 } else if (seg
->start
>= tag
->start
) {
756 /* This segment starts in the middle of the tag */
758 free_text_segment(seg
, NULL
);
759 line
->segments
= g_list_delete_link(line
->segments
, segs
);
760 if (line
->segments
== NULL
) {
761 free_text_line(line
, NULL
);
762 if (view
->list
== iter
) {
766 view
->list
= iter
->prev
;
768 alllines
= g_list_delete_link(alllines
, iter
);
772 seg
->start
= tag
->start
;
773 seg
->end
= tag
->end
- change
;
775 line
->length
-= change
;
776 /* XXX: Make things work if the tagged text spans over several lines. */
778 /* XXX: handle the rest of the conditions */
779 g_printerr("WTF! This needs to be handled properly!!\n");
785 view
->tags
= g_list_delete_link(view
->tags
, list
);
798 scroll_tv(GntWidget
*wid
, const char *key
, GntTextView
*tv
)
800 if (strcmp(key
, GNT_KEY_PGUP
) == 0) {
801 gnt_text_view_scroll(tv
, -(GNT_WIDGET(tv
)->priv
.height
- 2));
802 } else if (strcmp(key
, GNT_KEY_PGDOWN
) == 0) {
803 gnt_text_view_scroll(tv
, GNT_WIDGET(tv
)->priv
.height
- 2);
804 } else if (strcmp(key
, GNT_KEY_DOWN
) == 0) {
805 gnt_text_view_scroll(tv
, 1);
806 } else if (strcmp(key
, GNT_KEY_UP
) == 0) {
807 gnt_text_view_scroll(tv
, -1);
814 void gnt_text_view_attach_scroll_widget(GntTextView
*view
, GntWidget
*widget
)
816 g_signal_connect(G_OBJECT(widget
), "key_pressed", G_CALLBACK(scroll_tv
), view
);
819 void gnt_text_view_set_flag(GntTextView
*view
, GntTextViewFlag flag
)
824 /* Pager and editor setups */
833 cleanup_pageditor(void)
835 unlink(pageditor
.file
);
836 g_free(pageditor
.file
);
838 pageditor
.file
= NULL
;
843 editor_end_cb(int status
, gpointer data
)
847 if (g_file_get_contents(pageditor
.file
, &text
, NULL
, NULL
)) {
848 reset_text_view(pageditor
.tv
);
849 gnt_text_view_append_text_with_flags(pageditor
.tv
, text
, GNT_TEXT_FLAG_NORMAL
);
850 gnt_text_view_scroll(GNT_TEXT_VIEW(pageditor
.tv
), 0);
858 pager_end_cb(int status
, gpointer data
)
864 check_for_ext_cb(GntWidget
*widget
, const char *key
, GntTextView
*view
)
866 static const char *pager
= NULL
;
867 static const char *editor
= NULL
;
868 char *argv
[] = {NULL
, NULL
, NULL
};
869 static char path
[1024];
876 pager
= gnt_key_translate(gnt_style_get_from_name("pager", "key"));
879 editor
= gnt_key_translate(gnt_style_get_from_name("editor", "key"));
882 len
= g_snprintf(path
, sizeof(path
), "%s" G_DIR_SEPARATOR_S
"gnt", g_get_tmp_dir());
884 g_snprintf(path
+ len
, sizeof(path
) - len
, "XXXXXX");
887 if (strcmp(key
, pager
) == 0) {
888 if (g_object_get_data(G_OBJECT(widget
), "pager-for") != view
)
891 } else if (strcmp(key
, editor
) == 0) {
892 if (g_object_get_data(G_OBJECT(widget
), "editor-for") != view
)
899 file
= fdopen(g_mkstemp(path
), "wb");
902 fprintf(file
, "%s", view
->string
->str
);
906 pageditor
.file
= g_strdup(path
);
908 argv
[0] = gnt_style_get_from_name(pg
? "pager" : "editor", "path");
909 argv
[0] = argv
[0] ? argv
[0] : getenv(pg
? "PAGER" : "EDITOR");
910 argv
[0] = argv
[0] ? argv
[0] : (pg
? "less" : "vim");
912 ret
= gnt_giveup_console(NULL
, argv
, NULL
, NULL
, NULL
, NULL
, pg
? pager_end_cb
: editor_end_cb
, NULL
);
916 void gnt_text_view_attach_pager_widget(GntTextView
*view
, GntWidget
*pager
)
918 g_signal_connect(pager
, "key_pressed", G_CALLBACK(check_for_ext_cb
), view
);
919 g_object_set_data(G_OBJECT(pager
), "pager-for", view
);
922 void gnt_text_view_attach_editor_widget(GntTextView
*view
, GntWidget
*wid
)
924 g_signal_connect(wid
, "key_pressed", G_CALLBACK(check_for_ext_cb
), view
);
925 g_object_set_data(G_OBJECT(wid
), "editor-for", view
);