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
;
65 gnt_text_view_draw(GntWidget
*widget
)
67 GntTextView
*view
= GNT_TEXT_VIEW(widget
);
71 int comp
= 0; /* Used for top-aligned text */
72 gboolean has_scroll
= !(view
->flags
& GNT_TEXT_VIEW_NO_SCROLL
);
74 wbkgd(widget
->window
, gnt_color_pair(GNT_COLOR_NORMAL
));
75 werase(widget
->window
);
77 if ((view
->flags
& GNT_TEXT_VIEW_TOP_ALIGN
) &&
78 g_list_length(view
->list
) < widget
->priv
.height
) {
79 GList
*now
= view
->list
;
80 comp
= widget
->priv
.height
- g_list_length(view
->list
);
81 view
->list
= g_list_nth_prev(view
->list
, comp
);
83 view
->list
= g_list_first(now
);
84 comp
= widget
->priv
.height
- g_list_length(view
->list
);
90 for (i
= 0, lines
= view
->list
; i
< widget
->priv
.height
&& lines
; i
++, lines
= lines
->next
)
93 GntTextLine
*line
= lines
->data
;
95 wmove(widget
->window
, widget
->priv
.height
- 1 - i
- comp
, 0);
97 for (iter
= line
->segments
; iter
; iter
= iter
->next
)
99 GntTextSegment
*seg
= iter
->data
;
100 char *end
= view
->string
->str
+ seg
->end
;
102 chtype fl
= seg
->flags
;
104 if (select_start
< view
->string
->str
+ seg
->start
&& select_end
> view
->string
->str
+ seg
->end
) {
106 wattrset(widget
->window
, fl
);
107 wprintw(widget
->window
, "%s", (view
->string
->str
+ seg
->start
));
108 } else if (select_start
&& select_end
&&
109 ((select_start
>= view
->string
->str
+ seg
->start
&& select_start
<= view
->string
->str
+ seg
->end
) ||
110 (select_end
<= view
->string
->str
+ seg
->end
&& select_start
<= view
->string
->str
+ seg
->start
))) {
111 char *cur
= view
->string
->str
+ seg
->start
;
112 while (*cur
!= '\0') {
113 gchar
*last
= g_utf8_next_char(cur
);
115 if (cur
>= select_start
&& cur
<= select_end
)
119 str
= g_strndup(cur
, last
- cur
);
120 wattrset(widget
->window
, fl
);
121 waddstr(widget
->window
, str
);
123 cur
= g_utf8_next_char(cur
);
126 wattrset(widget
->window
, fl
);
127 wprintw(widget
->window
, "%s", (view
->string
->str
+ seg
->start
));
131 wattroff(widget
->window
, A_UNDERLINE
| A_BLINK
| A_REVERSE
);
132 whline(widget
->window
, ' ', widget
->priv
.width
- line
->length
- has_scroll
);
135 scrcol
= widget
->priv
.width
- 1;
136 rows
= widget
->priv
.height
- 2;
137 if (has_scroll
&& rows
> 0)
139 int total
= g_list_length(g_list_first(view
->list
));
140 int showing
, position
, up
, down
;
142 showing
= rows
* rows
/ total
+ 1;
143 showing
= MIN(rows
, showing
);
146 up
= g_list_length(lines
);
149 position
= (rows
- showing
) * up
/ MAX(1, up
+ down
);
150 position
= MAX((lines
!= NULL
), position
);
152 if (showing
+ position
> rows
)
153 position
= rows
- showing
;
155 if (showing
+ position
== rows
&& view
->list
&& view
->list
->prev
)
156 position
= MAX(1, rows
- 1 - showing
);
157 else if (showing
+ position
< rows
&& view
->list
&& !view
->list
->prev
)
158 position
= rows
- showing
;
160 mvwvline(widget
->window
, position
+ 1, scrcol
,
161 ACS_CKBOARD
| gnt_color_pair(GNT_COLOR_HIGHLIGHT_D
), showing
);
165 mvwaddch(widget
->window
, 0, scrcol
,
166 (lines
? ACS_UARROW
: ' ') | gnt_color_pair(GNT_COLOR_HIGHLIGHT_D
));
167 mvwaddch(widget
->window
, widget
->priv
.height
- 1, scrcol
,
168 ((view
->list
&& view
->list
->prev
) ? ACS_DARROW
: ' ') |
169 gnt_color_pair(GNT_COLOR_HIGHLIGHT_D
));
176 gnt_text_view_size_request(GntWidget
*widget
)
178 if (!GNT_WIDGET_IS_FLAG_SET(widget
, GNT_WIDGET_MAPPED
))
180 gnt_widget_set_size(widget
, 64, 20);
185 gnt_text_view_map(GntWidget
*widget
)
187 if (widget
->priv
.width
== 0 || widget
->priv
.height
== 0)
188 gnt_widget_size_request(widget
);
193 gnt_text_view_key_pressed(GntWidget
*widget
, const char *text
)
199 free_text_segment(gpointer data
, gpointer null
)
201 GntTextSegment
*seg
= data
;
206 free_text_line(gpointer data
, gpointer null
)
208 GntTextLine
*line
= data
;
209 g_list_foreach(line
->segments
, free_text_segment
, NULL
);
210 g_list_free(line
->segments
);
215 free_tag(gpointer data
, gpointer null
)
217 GntTextTag
*tag
= data
;
223 gnt_text_view_destroy(GntWidget
*widget
)
225 GntTextView
*view
= GNT_TEXT_VIEW(widget
);
226 view
->list
= g_list_first(view
->list
);
227 g_list_foreach(view
->list
, free_text_line
, NULL
);
228 g_list_free(view
->list
);
229 g_list_foreach(view
->tags
, free_tag
, NULL
);
230 g_list_free(view
->tags
);
231 g_string_free(view
->string
, TRUE
);
235 gnt_text_view_get_p(GntTextView
*view
, int x
, int y
)
238 GntWidget
*wid
= GNT_WIDGET(view
);
245 y
= wid
->priv
.height
- y
;
246 if (g_list_length(view
->list
) < y
) {
248 y
= g_list_length(view
->list
) - 1;
251 lines
= g_list_nth(view
->list
, y
- 1);
257 } while (line
&& !line
->segments
&& lines
);
259 if (!line
|| !line
->segments
) /* no valid line */
261 segs
= line
->segments
;
262 seg
= (GntTextSegment
*)segs
->data
;
263 pos
= view
->string
->str
+ seg
->start
;
264 x
= MIN(x
, line
->length
);
267 pos
= g_utf8_next_char(pos
);
268 u
= g_utf8_to_ucs4(pos
, -1, NULL
, NULL
, NULL
);
269 if (u
&& g_unichar_iswide(*u
))
277 select_word_text(GntTextView
*view
, gchar
*c
)
282 while ((t
= g_utf8_prev_char(start
))) {
283 if (!g_ascii_isspace(*t
)) {
284 if (start
== view
->string
->str
)
290 while ((t
= g_utf8_next_char(end
))) {
291 if (!g_ascii_isspace(*t
))
296 select_start
= start
;
298 endsize
= g_utf8_next_char(select_end
); /* End at the correct byte */
299 return g_string_new_len(start
, endsize
- start
);
302 static gboolean
too_slow(gpointer n
)
304 double_click
= FALSE
;
309 gnt_text_view_clicked(GntWidget
*widget
, GntMouseEvent event
, int x
, int y
)
311 if (event
== GNT_MOUSE_SCROLL_UP
) {
312 gnt_text_view_scroll(GNT_TEXT_VIEW(widget
), -1);
313 } else if (event
== GNT_MOUSE_SCROLL_DOWN
) {
314 gnt_text_view_scroll(GNT_TEXT_VIEW(widget
), 1);
315 } else if (event
== GNT_LEFT_MOUSE_DOWN
) {
316 select_start
= gnt_text_view_get_p(GNT_TEXT_VIEW(widget
), x
- widget
->priv
.x
, y
- widget
->priv
.y
);
317 g_timeout_add(500, too_slow
, NULL
);
318 } else if (event
== GNT_MOUSE_UP
) {
321 select_end
= gnt_text_view_get_p(GNT_TEXT_VIEW(widget
), x
- widget
->priv
.x
, y
- widget
->priv
.y
);
322 if (select_end
< select_start
) {
323 gchar
*t
= select_start
;
324 select_start
= select_end
;
327 if (select_start
== select_end
) {
329 clip
= select_word_text(GNT_TEXT_VIEW(widget
), select_start
);
330 double_click
= FALSE
;
335 gnt_widget_draw(widget
);
339 gchar
*endsize
= g_utf8_next_char(select_end
); /* End at the correct byte */
340 clip
= g_string_new_len(select_start
, endsize
- select_start
);
342 gnt_widget_draw(widget
);
343 gnt_set_clipboard_string(clip
->str
);
344 g_string_free(clip
, TRUE
);
352 gnt_text_view_reflow(GntTextView
*view
)
354 /* This is pretty ugly, and inefficient. Someone do something about it. */
356 GList
*back
, *iter
, *list
;
358 int pos
= 0; /* no. of 'real' lines */
368 back
= g_list_last(view
->list
);
371 string
= view
->string
;
373 gnt_text_view_clear(view
);
375 view
->string
= g_string_set_size(view
->string
, string
->len
);
376 view
->string
->len
= 0;
377 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(view
), GNT_WIDGET_DRAWING
);
379 for (; back
; back
= back
->prev
) {
381 if (back
->next
&& !line
->soft
) {
382 gnt_text_view_append_text_with_flags(view
, "\n", GNT_TEXT_FLAG_NORMAL
);
385 for (iter
= line
->segments
; iter
; iter
= iter
->next
) {
386 GntTextSegment
*seg
= iter
->data
;
387 char *start
= string
->str
+ seg
->start
;
388 char *end
= string
->str
+ seg
->end
;
391 gnt_text_view_append_text_with_flags(view
, start
, seg
->tvflag
);
394 free_text_line(line
, NULL
);
398 list
= view
->list
= g_list_first(view
->list
);
399 /* Go back to the line that was in view before resizing started */
401 while (((GntTextLine
*)list
->data
)->soft
)
406 GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(view
), GNT_WIDGET_DRAWING
);
407 if (GNT_WIDGET(view
)->window
)
408 gnt_widget_draw(GNT_WIDGET(view
));
409 g_string_free(string
, TRUE
);
413 gnt_text_view_size_changed(GntWidget
*widget
, int w
, int h
)
415 if (w
!= widget
->priv
.width
&& GNT_WIDGET_IS_FLAG_SET(widget
, GNT_WIDGET_MAPPED
)) {
416 gnt_text_view_reflow(GNT_TEXT_VIEW(widget
));
421 gnt_text_view_class_init(GntTextViewClass
*klass
)
423 parent_class
= GNT_WIDGET_CLASS(klass
);
424 parent_class
->destroy
= gnt_text_view_destroy
;
425 parent_class
->draw
= gnt_text_view_draw
;
426 parent_class
->map
= gnt_text_view_map
;
427 parent_class
->size_request
= gnt_text_view_size_request
;
428 parent_class
->key_pressed
= gnt_text_view_key_pressed
;
429 parent_class
->clicked
= gnt_text_view_clicked
;
430 parent_class
->size_changed
= gnt_text_view_size_changed
;
436 gnt_text_view_init(GTypeInstance
*instance
, gpointer
class)
438 GntWidget
*widget
= GNT_WIDGET(instance
);
439 GntTextView
*view
= GNT_TEXT_VIEW(widget
);
440 GntTextLine
*line
= g_new0(GntTextLine
, 1);
442 GNT_WIDGET_SET_FLAGS(widget
, GNT_WIDGET_NO_BORDER
| GNT_WIDGET_NO_SHADOW
|
443 GNT_WIDGET_GROW_Y
| GNT_WIDGET_GROW_X
);
444 widget
->priv
.minw
= 5;
445 widget
->priv
.minh
= 2;
446 view
->string
= g_string_new(NULL
);
447 view
->list
= g_list_append(view
->list
, line
);
452 /******************************************************************************
454 *****************************************************************************/
456 gnt_text_view_get_gtype(void)
458 static GType type
= 0;
462 static const GTypeInfo info
= {
463 sizeof(GntTextViewClass
),
464 NULL
, /* base_init */
465 NULL
, /* base_finalize */
466 (GClassInitFunc
)gnt_text_view_class_init
,
467 NULL
, /* class_finalize */
468 NULL
, /* class_data */
471 gnt_text_view_init
, /* instance_init */
472 NULL
/* value_table */
475 type
= g_type_register_static(GNT_TYPE_WIDGET
,
483 GntWidget
*gnt_text_view_new()
485 GntWidget
*widget
= g_object_new(GNT_TYPE_TEXT_VIEW
, NULL
);
490 void gnt_text_view_append_text_with_flags(GntTextView
*view
, const char *text
, GntTextFormatFlags flags
)
492 gnt_text_view_append_text_with_tag(view
, text
, flags
, NULL
);
495 void gnt_text_view_append_text_with_tag(GntTextView
*view
, const char *text
,
496 GntTextFormatFlags flags
, const char *tagname
)
498 GntWidget
*widget
= GNT_WIDGET(view
);
500 const char *start
, *end
;
501 GList
*list
= view
->list
;
504 gboolean has_scroll
= !(view
->flags
& GNT_TEXT_VIEW_NO_SCROLL
);
505 gboolean wrap_word
= !(view
->flags
& GNT_TEXT_VIEW_WRAP_CHAR
);
507 if (text
== NULL
|| *text
== '\0')
510 fl
= gnt_text_format_flag_to_chtype(flags
);
512 len
= view
->string
->len
;
513 view
->string
= g_string_append(view
->string
, text
);
516 GntTextTag
*tag
= g_new0(GntTextTag
, 1);
517 tag
->name
= g_strdup(tagname
);
519 tag
->end
= view
->string
->len
;
520 view
->tags
= g_list_append(view
->tags
, tag
);
523 view
->list
= g_list_first(view
->list
);
525 start
= end
= view
->string
->str
+ len
;
529 GntTextSegment
*seg
= NULL
;
531 if (*end
== '\n' || *end
== '\r') {
532 if (!strncmp(end
, "\r\n", 2))
536 gnt_text_view_next_line(view
);
537 view
->list
= g_list_first(view
->list
);
541 line
= view
->list
->data
;
542 if (line
->length
== widget
->priv
.width
- has_scroll
) {
543 /* The last added line was exactly the same width as the widget */
544 line
= g_new0(GntTextLine
, 1);
546 view
->list
= g_list_prepend(view
->list
, line
);
549 if ((end
= strchr(start
, '\r')) != NULL
||
550 (end
= strchr(start
, '\n')) != NULL
) {
551 len
= gnt_util_onscreen_width(start
, end
- has_scroll
);
552 if (widget
->priv
.width
> 0 &&
553 len
>= widget
->priv
.width
- line
->length
- has_scroll
) {
559 end
= gnt_util_onscreen_width_to_pointer(start
,
560 widget
->priv
.width
- line
->length
- has_scroll
, &len
);
562 /* Try to append to the previous segment if possible */
563 if (line
->segments
) {
564 seg
= g_list_last(line
->segments
)->data
;
565 if (seg
->flags
!= fl
)
570 seg
= g_new0(GntTextSegment
, 1);
571 seg
->start
= start
- view
->string
->str
;
574 line
->segments
= g_list_append(line
->segments
, seg
);
578 if (wrap_word
&& *end
&& *end
!= '\n' && *end
!= '\r') {
579 const char *tmp
= end
;
580 while (end
&& *end
!= '\n' && *end
!= '\r' && !g_ascii_isspace(*end
)) {
581 end
= g_utf8_find_prev_char(seg
->start
+ view
->string
->str
, end
);
583 if (!end
|| !g_ascii_isspace(*end
))
586 end
++; /* Remove the space */
588 line
= g_new0(GntTextLine
, 1);
590 view
->list
= g_list_prepend(view
->list
, line
);
592 seg
->end
= end
- view
->string
->str
;
599 gnt_widget_draw(widget
);
602 void gnt_text_view_scroll(GntTextView
*view
, int scroll
)
606 view
->list
= g_list_first(view
->list
);
610 GList
*list
= g_list_nth_prev(view
->list
, scroll
);
612 list
= g_list_first(view
->list
);
617 GList
*list
= g_list_nth(view
->list
, -scroll
);
619 list
= g_list_last(view
->list
);
623 gnt_widget_draw(GNT_WIDGET(view
));
626 void gnt_text_view_next_line(GntTextView
*view
)
628 GntTextLine
*line
= g_new0(GntTextLine
, 1);
629 GList
*list
= view
->list
;
631 view
->list
= g_list_prepend(g_list_first(view
->list
), line
);
633 gnt_widget_draw(GNT_WIDGET(view
));
636 chtype
gnt_text_format_flag_to_chtype(GntTextFormatFlags flags
)
640 if (flags
& GNT_TEXT_FLAG_BOLD
)
642 if (flags
& GNT_TEXT_FLAG_UNDERLINE
)
644 if (flags
& GNT_TEXT_FLAG_BLINK
)
647 if (flags
& GNT_TEXT_FLAG_DIM
)
648 fl
|= (A_DIM
| gnt_color_pair(GNT_COLOR_DISABLED
));
649 else if (flags
& GNT_TEXT_FLAG_HIGHLIGHT
)
650 fl
|= (A_DIM
| gnt_color_pair(GNT_COLOR_HIGHLIGHT
));
652 fl
|= gnt_color_pair(GNT_COLOR_NORMAL
);
657 void gnt_text_view_clear(GntTextView
*view
)
661 g_list_foreach(view
->list
, free_text_line
, NULL
);
662 g_list_free(view
->list
);
665 line
= g_new0(GntTextLine
, 1);
666 view
->list
= g_list_append(view
->list
, line
);
668 g_string_free(view
->string
, TRUE
);
669 view
->string
= g_string_new(NULL
);
671 if (GNT_WIDGET(view
)->window
)
672 gnt_widget_draw(GNT_WIDGET(view
));
675 int gnt_text_view_get_lines_below(GntTextView
*view
)
678 GList
*list
= view
->list
;
679 while ((list
= list
->prev
))
684 int gnt_text_view_get_lines_above(GntTextView
*view
)
687 GList
*list
= view
->list
;
688 list
= g_list_nth(view
->list
, GNT_WIDGET(view
)->priv
.height
);
691 while ((list
= list
->next
))
697 * XXX: There are quite possibly more than a few bugs here.
699 int gnt_text_view_tag_change(GntTextView
*view
, const char *name
, const char *text
, gboolean all
)
701 GList
*alllines
= g_list_first(view
->list
);
702 GList
*list
, *next
, *iter
, *inext
;
703 const int text_length
= text
? strlen(text
) : 0;
705 for (list
= view
->tags
; list
; list
= next
) {
706 GntTextTag
*tag
= list
->data
;
708 if (strcmp(tag
->name
, name
) == 0) {
710 char *before
, *after
;
714 before
= g_strndup(view
->string
->str
, tag
->start
);
715 after
= g_strdup(view
->string
->str
+ tag
->end
);
716 change
= (tag
->end
- tag
->start
) - text_length
;
718 g_string_printf(view
->string
, "%s%s%s", before
, text
? text
: "", after
);
722 /* Update the offsets of the next tags */
723 for (iter
= next
; iter
; iter
= iter
->next
) {
724 GntTextTag
*t
= iter
->data
;
729 /* Update the offsets of the segments */
730 for (iter
= alllines
; iter
; iter
= inext
) {
732 GntTextLine
*line
= iter
->data
;
734 for (segs
= line
->segments
; segs
; segs
= snext
) {
735 GntTextSegment
*seg
= segs
->data
;
737 if (seg
->start
>= tag
->end
) {
738 /* The segment is somewhere after the tag */
739 seg
->start
-= change
;
741 } else if (seg
->end
<= tag
->start
) {
742 /* This segment is somewhere in front of the tag */
743 } else if (seg
->start
>= tag
->start
) {
744 /* This segment starts in the middle of the tag */
746 free_text_segment(seg
, NULL
);
747 line
->segments
= g_list_delete_link(line
->segments
, segs
);
748 if (line
->segments
== NULL
) {
749 free_text_line(line
, NULL
);
750 if (view
->list
== iter
) {
754 view
->list
= iter
->prev
;
756 alllines
= g_list_delete_link(alllines
, iter
);
760 seg
->start
= tag
->start
;
761 seg
->end
= tag
->end
- change
;
763 line
->length
-= change
;
764 /* XXX: Make things work if the tagged text spans over several lines. */
766 /* XXX: handle the rest of the conditions */
767 g_printerr("WTF! This needs to be handled properly!!\n");
773 view
->tags
= g_list_delete_link(view
->tags
, list
);
786 scroll_tv(GntWidget
*wid
, const char *key
, GntTextView
*tv
)
788 if (strcmp(key
, GNT_KEY_PGUP
) == 0) {
789 gnt_text_view_scroll(tv
, -(GNT_WIDGET(tv
)->priv
.height
- 2));
790 } else if (strcmp(key
, GNT_KEY_PGDOWN
) == 0) {
791 gnt_text_view_scroll(tv
, GNT_WIDGET(tv
)->priv
.height
- 2);
792 } else if (strcmp(key
, GNT_KEY_DOWN
) == 0) {
793 gnt_text_view_scroll(tv
, 1);
794 } else if (strcmp(key
, GNT_KEY_UP
) == 0) {
795 gnt_text_view_scroll(tv
, -1);
802 void gnt_text_view_attach_scroll_widget(GntTextView
*view
, GntWidget
*widget
)
804 g_signal_connect(G_OBJECT(widget
), "key_pressed", G_CALLBACK(scroll_tv
), view
);
807 void gnt_text_view_set_flag(GntTextView
*view
, GntTextViewFlag flag
)
812 /* Pager and editor setups */
823 unlink(pageditor
.file
);
824 g_free(pageditor
.file
);
826 pageditor
.file
= NULL
;
831 editor_end_cb(int status
, gpointer data
)
835 if (g_file_get_contents(pageditor
.file
, &text
, NULL
, NULL
)) {
836 gnt_text_view_clear(pageditor
.tv
);
837 gnt_text_view_append_text_with_flags(pageditor
.tv
, text
, GNT_TEXT_FLAG_NORMAL
);
838 gnt_text_view_scroll(GNT_TEXT_VIEW(pageditor
.tv
), 0);
846 pager_end_cb(int status
, gpointer data
)
852 check_for_ext_cb(GntWidget
*widget
, const char *key
, GntTextView
*view
)
854 static const char *pager
= NULL
;
855 static const char *editor
= NULL
;
856 char *argv
[] = {NULL
, NULL
, NULL
};
857 static char path
[1024];
864 pager
= gnt_key_translate(gnt_style_get_from_name("pager", "key"));
867 editor
= gnt_key_translate(gnt_style_get_from_name("editor", "key"));
870 len
= g_snprintf(path
, sizeof(path
), "%s" G_DIR_SEPARATOR_S
"gnt", g_get_tmp_dir());
872 g_snprintf(path
+ len
, sizeof(path
) - len
, "XXXXXX");
875 if (strcmp(key
, pager
) == 0) {
876 if (g_object_get_data(G_OBJECT(widget
), "pager-for") != view
)
879 } else if (strcmp(key
, editor
) == 0) {
880 if (g_object_get_data(G_OBJECT(widget
), "editor-for") != view
)
887 file
= fdopen(g_mkstemp(path
), "wb");
890 fprintf(file
, "%s", view
->string
->str
);
894 pageditor
.file
= g_strdup(path
);
896 argv
[0] = gnt_style_get_from_name(pg
? "pager" : "editor", "path");
897 argv
[0] = argv
[0] ? argv
[0] : getenv(pg
? "PAGER" : "EDITOR");
898 argv
[0] = argv
[0] ? argv
[0] : (pg
? "less" : "vim");
900 ret
= gnt_giveup_console(NULL
, argv
, NULL
, NULL
, NULL
, NULL
, pg
? pager_end_cb
: editor_end_cb
, NULL
);
904 void gnt_text_view_attach_pager_widget(GntTextView
*view
, GntWidget
*pager
)
906 g_signal_connect(pager
, "key_pressed", G_CALLBACK(check_for_ext_cb
), view
);
907 g_object_set_data(G_OBJECT(pager
), "pager-for", view
);
910 void gnt_text_view_attach_editor_widget(GntTextView
*view
, GntWidget
*wid
)
912 g_signal_connect(wid
, "key_pressed", G_CALLBACK(check_for_ext_cb
), view
);
913 g_object_set_data(G_OBJECT(wid
), "editor-for", view
);