3 Minimum Profit - Programmer Text Editor
7 Copyright (C) 1991-2011 Angel Ortega <angel@triptico.com>
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 http://www.triptico.com
39 #include <gdk/gdkkeysyms.h>
52 static GtkWidget
*window
= NULL
;
53 static GtkWidget
*file_tabs
= NULL
;
54 static GtkWidget
*area
= NULL
;
55 static GtkWidget
*scrollbar
= NULL
;
56 static GtkWidget
*status
= NULL
;
57 static GtkWidget
*menu_bar
= NULL
;
58 static GtkIMContext
*im
= NULL
;
60 /* character read from the keyboard */
61 static wchar_t im_char
[2];
63 /* font information */
64 static int font_width
= 0;
65 static int font_height
= 0;
66 static PangoFontDescription
*font
= NULL
;
69 static GdkColor
*inks
= NULL
;
70 static GdkColor
*papers
= NULL
;
71 static int *underlines
= NULL
;
73 /* true if the selection is ours */
74 static int got_selection
= 0;
76 /* hack for active waiting for the selection */
77 static int wait_for_selection
= 0;
79 /* global modal status */
80 /* code for the 'normal' attribute */
81 static int normal_attr
= 0;
83 /* mp.drv.form() controls */
85 static GtkWidget
**form_widgets
= NULL
;
86 static mpdm_t form_args
= NULL
;
87 static mpdm_t form_values
= NULL
;
90 static int mouse_down
= 0;
93 static mpdm_t timer_func
= NULL
;
95 /* maximize wanted? */
96 static int maximize
= 0;
100 /** support functions **/
104 static char *wcs_to_utf8(const wchar_t * wptr
)
105 /* converts a wcs to utf-8 */
112 /* do the conversion */
113 ptr
= g_convert((const gchar
*) wptr
, (i
+ 1) * sizeof(wchar_t),
114 "UTF-8", "WCHAR_T", NULL
, &o
, NULL
);
120 static char *v_to_utf8(mpdm_t v
)
126 ptr
= wcs_to_utf8(mpdm_string(v
));
133 static wchar_t *utf8_to_wcs(const char *ptr
)
134 /* converts utf-8 to wcs */
141 /* do the conversion */
142 wptr
= (wchar_t *) g_convert((gchar
*) ptr
, i
+ 1,
143 "WCHAR_T", "UTF-8", NULL
, &o
, NULL
);
149 static void update_window_size(void)
150 /* updates the viewport size in characters */
156 /* get font metrics */
157 pa
= gtk_widget_create_pango_layout(area
, "m");
158 pango_layout_set_font_description(pa
, font
);
159 pango_layout_get_pixel_size(pa
, &font_width
, &font_height
);
162 /* calculate the size in chars */
163 tx
= (area
->allocation
.width
/ font_width
);
164 ty
= (area
->allocation
.height
/ font_height
) + 1;
166 /* store the 'window' size */
167 v
= mpdm_hget_s(mp
, L
"window");
168 mpdm_hset_s(v
, L
"tx", MPDM_I(tx
));
169 mpdm_hset_s(v
, L
"ty", MPDM_I(ty
));
171 /* rebuild the pixmap for the double buffer */
175 static void build_fonts(void)
176 /* builds the fonts */
180 const char *font_face
= "Mono";
185 pango_font_description_free(font
);
187 /* get current configuration */
188 if ((c
= mpdm_hget_s(mp
, L
"config")) != NULL
) {
191 if ((v
= mpdm_hget_s(c
, L
"font_size")) != NULL
)
192 font_size
= mpdm_ival(v
);
194 mpdm_hset_s(c
, L
"font_size", MPDM_I(font_size
));
196 if ((v
= mpdm_hget_s(c
, L
"font_face")) != NULL
) {
197 w
= mpdm_ref(MPDM_2MBS(v
->data
));
201 mpdm_hset_s(c
, L
"font_face", MPDM_MBS(font_face
));
204 snprintf(tmp
, sizeof(tmp
) - 1, "%s %d", font_face
, font_size
);
205 tmp
[sizeof(tmp
) - 1] = '\0';
207 font
= pango_font_description_from_string(tmp
);
208 update_window_size();
214 static void build_color(GdkColor
* gdkcolor
, int rgb
)
218 gdkcolor
->blue
= (rgb
& 0x000000ff) << 8;
219 gdkcolor
->green
= (rgb
& 0x0000ff00);
220 gdkcolor
->red
= (rgb
& 0x00ff0000) >> 8;
221 gdk_colormap_alloc_color(gdk_colormap_get_system(), gdkcolor
, FALSE
,
226 static void build_colors(void)
227 /* builds the colors */
234 /* gets the color definitions and attribute names */
235 colors
= mpdm_hget_s(mp
, L
"colors");
236 l
= mpdm_ref(mpdm_keys(colors
));
239 /* redim the structures */
240 inks
= realloc(inks
, sizeof(GdkColor
) * s
);
241 papers
= realloc(papers
, sizeof(GdkColor
) * s
);
242 underlines
= realloc(underlines
, sizeof(int) * s
);
244 /* loop the colors */
245 for (n
= 0; n
< s
&& (c
= mpdm_aget(l
, n
)) != NULL
; n
++) {
246 mpdm_t d
= mpdm_hget(colors
, c
);
247 mpdm_t v
= mpdm_hget_s(d
, L
"gui");
249 /* store the 'normal' attribute */
250 if (wcscmp(mpdm_string(c
), L
"normal") == 0)
254 mpdm_hset_s(d
, L
"attr", MPDM_I(n
));
256 build_color(&inks
[n
], mpdm_ival(mpdm_aget(v
, 0)));
257 build_color(&papers
[n
], mpdm_ival(mpdm_aget(v
, 1)));
260 v
= mpdm_hget_s(d
, L
"flags");
261 underlines
[n
] = mpdm_seek_s(v
, L
"underline", 1) != -1 ? 1 : 0;
263 if (mpdm_seek_s(v
, L
"reverse", 1) != -1) {
276 /** menu functions **/
278 static void redraw(void);
280 static void menu_item_callback(mpdm_t action
)
281 /* menu click callback */
283 mp_process_action(action
);
286 if (mp_exit_requested
)
291 static void build_submenu(GtkWidget
* menu
, mpdm_t labels
)
292 /* build a submenu */
295 GtkWidget
*menu_item
;
299 for (n
= 0; n
< mpdm_size(labels
); n
++) {
301 mpdm_t v
= mpdm_aget(labels
, n
);
303 /* if the action is a separator... */
304 if (*((wchar_t *) v
->data
) == L
'-')
305 menu_item
= gtk_menu_item_new();
309 ptr
= v_to_utf8(mp_menu_label(v
));
310 menu_item
= gtk_menu_item_new_with_label(ptr
);
314 gtk_menu_append(GTK_MENU(menu
), menu_item
);
315 g_signal_connect_swapped(G_OBJECT(menu_item
), "activate",
316 G_CALLBACK(menu_item_callback
), v
);
317 gtk_widget_show(menu_item
);
324 static void build_menu(void)
325 /* builds the menu */
327 static mpdm_t prev_menu
= NULL
;
331 /* gets the current menu */
332 if ((m
= mpdm_hget_s(mp
, L
"menu")) == NULL
)
335 /* if it's the same, do nothing */
336 if (mpdm_cmp(m
, prev_menu
) == 0)
339 /* create a new menu */
340 menu_bar
= gtk_menu_bar_new();
342 for (n
= 0; n
< mpdm_size(m
); n
++) {
347 GtkWidget
*menu_item
;
350 /* get the label and the items */
351 mi
= mpdm_aget(m
, n
);
352 v
= mpdm_aget(mi
, 0);
354 if ((ptr
= v_to_utf8(mpdm_gettext(v
))) == NULL
)
357 /* change the & by _ for the mnemonic */
358 for (i
= 0; ptr
[i
]; i
++)
362 /* add the menu and the label */
363 menu
= gtk_menu_new();
364 menu_item
= gtk_menu_item_new_with_mnemonic(ptr
);
367 gtk_widget_show(menu_item
);
368 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item
), menu
);
369 gtk_menu_bar_append(GTK_MENU_BAR(menu_bar
), menu_item
);
371 /* now loop the items */
372 build_submenu(menu
, mpdm_aget(mi
, 1));
377 /** main area drawing functions **/
379 static void switch_page(GtkNotebook
* notebook
, gpointer
* page
,
380 gint pg_num
, gpointer data
)
381 /* 'switch_page' handler (filetabs) */
383 /* sets the active one */
384 mpdm_hset_s(mp
, L
"active_i", MPDM_I(pg_num
));
386 gtk_widget_grab_focus(area
);
391 static void draw_filetabs(void)
392 /* draws the filetabs */
394 static mpdm_t last
= NULL
;
398 names
= mpdm_ref(mp_get_doc_names());
400 /* disconnect redraw signal to avoid infinite loops */
401 g_signal_handlers_disconnect_by_func(G_OBJECT(file_tabs
),
402 G_CALLBACK(switch_page
), NULL
);
404 /* is the list different from the previous one? */
405 if (mpdm_cmp(names
, last
) != 0) {
407 /* delete the current tabs */
408 for (n
= 0; n
< mpdm_size(last
); n
++)
409 gtk_notebook_remove_page(GTK_NOTEBOOK(file_tabs
), 0);
411 /* create the new ones */
412 for (n
= 0; n
< mpdm_size(names
); n
++) {
416 mpdm_t v
= mpdm_aget(names
, n
);
418 if ((ptr
= v_to_utf8(v
)) != NULL
) {
419 p
= gtk_label_new(ptr
);
422 f
= gtk_frame_new(NULL
);
425 gtk_notebook_append_page(GTK_NOTEBOOK(file_tabs
), f
, p
);
431 /* store for the next time */
433 last
= mpdm_ref(names
);
438 /* set the active one */
439 gtk_notebook_set_current_page(GTK_NOTEBOOK(file_tabs
),
440 mpdm_ival(mpdm_hget_s(mp
, L
"active_i")));
442 /* reconnect signal */
443 g_signal_connect(G_OBJECT(file_tabs
), "switch_page",
444 G_CALLBACK(switch_page
), NULL
);
446 gtk_widget_grab_focus(area
);
450 static void draw_status(void)
451 /* draws the status line */
455 if ((ptr
= v_to_utf8(mp_build_status_line())) != NULL
) {
456 gtk_label_set_text(GTK_LABEL(status
), ptr
);
462 static gint
scroll_event(GtkWidget
* widget
, GdkEventScroll
* event
)
463 /* 'scroll_event' handler (mouse wheel) */
467 switch (event
->direction
) {
469 ptr
= L
"mouse-wheel-up";
471 case GDK_SCROLL_DOWN
:
472 ptr
= L
"mouse-wheel-down";
474 case GDK_SCROLL_LEFT
:
475 ptr
= L
"mouse-wheel-left";
477 case GDK_SCROLL_RIGHT
:
478 ptr
= L
"mouse-wheel-right";
483 mp_process_event(MPDM_S(ptr
));
491 static void value_changed(GtkAdjustment
* adj
, gpointer
* data
)
492 /* 'value_changed' handler (scrollbar) */
494 int i
= (int) gtk_adjustment_get_value(adj
);
499 /* get current y position */
501 txt
= mpdm_hget_s(doc
, L
"txt");
502 y
= mpdm_ival(mpdm_hget_s(txt
, L
"y"));
504 /* if it's different, set and redraw */
507 mpdm_hset_s(txt
, L
"vy", MPDM_I(i
));
513 static void draw_scrollbar(void)
514 /* updates the scrollbar */
516 GtkAdjustment
*adjustment
;
521 /* gets the active document */
522 if ((d
= mp_active()) == NULL
)
525 /* get the coordinates */
526 v
= mpdm_hget_s(d
, L
"txt");
527 pos
= mpdm_ival(mpdm_hget_s(v
, L
"vy"));
528 max
= mpdm_size(mpdm_hget_s(v
, L
"lines"));
530 v
= mpdm_hget_s(mp
, L
"window");
531 size
= mpdm_ival(mpdm_hget_s(v
, L
"ty"));
533 adjustment
= gtk_range_get_adjustment(GTK_RANGE(scrollbar
));
535 /* disconnect to avoid infinite loops */
536 g_signal_handlers_disconnect_by_func(G_OBJECT(adjustment
),
537 G_CALLBACK(value_changed
), NULL
);
539 gtk_adjustment_set_step_increment(adjustment
, (gdouble
) 1);
540 gtk_adjustment_set_upper(adjustment
, (gdouble
) max
);
541 gtk_adjustment_set_page_size(adjustment
, (gdouble
) size
);
542 gtk_adjustment_set_page_increment(adjustment
, (gdouble
) size
);
543 gtk_adjustment_set_value(adjustment
, (gdouble
) pos
);
545 gtk_range_set_adjustment(GTK_RANGE(scrollbar
), adjustment
);
547 gtk_adjustment_changed(adjustment
);
548 gtk_adjustment_value_changed(adjustment
);
551 g_signal_connect(G_OBJECT
552 (gtk_range_get_adjustment(GTK_RANGE(scrollbar
))),
553 "value_changed", G_CALLBACK(value_changed
), NULL
);
557 static void gtk_drv_paint(mpdm_t doc
, int optimize
)
558 /* GTK document draw function */
566 gtk_window_maximize(GTK_WINDOW(window
));
568 /* no gc? create it */
572 if ((d
= mp_draw(doc
, optimize
)) == NULL
)
579 gr
.width
= area
->allocation
.width
;
580 gr
.height
= font_height
;
582 cr
= gdk_cairo_create(gtk_widget_get_window(area
));
583 for (n
= 0; n
< mpdm_size(d
); n
++) {
586 mpdm_t l
= mpdm_aget(d
, n
);
593 /* create the pango stuff */
594 pl
= gtk_widget_create_pango_layout(area
, NULL
);
595 pango_layout_set_font_description(pl
, font
);
596 pal
= pango_attr_list_new();
598 for (m
= u
= p
= 0; m
< mpdm_size(l
); m
++, u
= p
) {
604 /* get the attribute and the string */
605 attr
= mpdm_ival(mpdm_aget(l
, m
++));
608 /* convert the string to utf8 */
611 /* add to the full line */
612 str
= mpdm_poke(str
, &p
, ptr
, strlen(ptr
), 1);
616 /* create the background if it's
617 different from the default */
618 if (papers
[attr
].red
!= papers
[normal_attr
].red
||
619 papers
[attr
].green
!= papers
[normal_attr
].green
||
620 papers
[attr
].blue
!= papers
[normal_attr
].blue
) {
621 pa
= pango_attr_background_new(papers
[attr
].red
,
628 pango_attr_list_insert(pal
, pa
);
632 if (underlines
[attr
]) {
633 pa
= pango_attr_underline_new(TRUE
);
638 pango_attr_list_insert(pal
, pa
);
641 /* foreground color */
642 pa
= pango_attr_foreground_new(inks
[attr
].red
,
649 pango_attr_list_insert(pal
, pa
);
652 /* store the attributes */
653 pango_layout_set_attributes(pl
, pal
);
654 pango_attr_list_unref(pal
);
656 /* store and free the text */
657 pango_layout_set_text(pl
, str
, p
);
660 /* draw the background */
661 gdk_cairo_set_source_color(cr
, &papers
[normal_attr
]);
662 cairo_rectangle(cr
, 0, n
* font_height
, gr
.width
, gr
.height
);
666 cairo_move_to(cr
, 2, n
* font_height
);
667 pango_cairo_show_layout(cr
, pl
);
669 /* dump the pixmap */
683 static void redraw(void)
685 if (mpdm_size(mpdm_hget_s(mp
, L
"docs")))
686 gtk_drv_paint(mp_active(), 0);
690 static gint
delete_event(GtkWidget
* w
, GdkEvent
* e
, gpointer data
)
691 /* 'delete_event' handler */
693 mp_process_event(MPDM_LS(L
"close-window"));
695 return mp_exit_requested
? FALSE
: TRUE
;
699 static void destroy(GtkWidget
* w
, gpointer data
)
700 /* 'destroy' handler */
706 static gint
key_release_event(GtkWidget
* widget
, GdkEventKey
* event
,
708 /* 'key_release_event' handler */
710 if (mp_keypress_throttle(0))
711 gtk_drv_paint(mp_active(), 0);
717 static gint
key_press_event(GtkWidget
* widget
, GdkEventKey
* event
,
719 /* 'key_press_event' handler */
723 gtk_im_context_filter_keypress(im
, event
);
725 /* set mp.shift_pressed */
726 if (event
->state
& (GDK_SHIFT_MASK
))
727 mpdm_hset_s(mp
, L
"shift_pressed", MPDM_I(1));
729 /* reserve alt for menu mnemonics */
730 /* if (GDK_MOD1_MASK & event->state)
733 if (event
->state
& (GDK_CONTROL_MASK
)) {
734 switch (event
->keyval
) {
736 ptr
= L
"ctrl-cursor-up";
739 ptr
= L
"ctrl-cursor-down";
742 ptr
= L
"ctrl-cursor-left";
745 ptr
= L
"ctrl-cursor-right";
748 ptr
= L
"ctrl-page-up";
751 ptr
= L
"ctrl-page-down";
763 ptr
= L
"ctrl-kp-plus";
765 case GDK_KP_Subtract
:
766 ptr
= L
"ctrl-kp-minus";
768 case GDK_KP_Multiply
:
769 ptr
= L
"ctrl-kp-multiply";
772 ptr
= L
"ctrl-kp-divide";
814 case GDK_Cyrillic_ve
:
820 case GDK_Cyrillic_tse
:
823 case GDK_Cyrillic_de
:
826 case GDK_Cyrillic_ie
:
829 case GDK_Cyrillic_ef
:
832 case GDK_Cyrillic_ghe
:
838 case GDK_Cyrillic_shorti
:
841 case GDK_Cyrillic_ka
:
844 case GDK_Cyrillic_el
:
847 case GDK_Cyrillic_em
:
850 case GDK_Cyrillic_en
:
856 case GDK_Cyrillic_pe
:
859 case GDK_Cyrillic_ya
:
862 case GDK_Cyrillic_er
:
865 case GDK_Cyrillic_es
:
868 case GDK_Cyrillic_te
:
871 case GDK_Cyrillic_softsign
:
874 case GDK_Cyrillic_yeru
:
877 case GDK_Cyrillic_ze
:
880 case GDK_Cyrillic_sha
:
886 case GDK_Cyrillic_shcha
:
889 case GDK_Cyrillic_che
:
895 char c
= event
->keyval
& 0xdf;
980 if (event
->state
& (GDK_MOD1_MASK
)) {
981 switch (event
->keyval
) {
983 ptr
= L
"alt-cursor-up";
986 ptr
= L
"alt-cursor-down";
989 ptr
= L
"alt-cursor-left";
992 ptr
= L
"alt-cursor-right";
995 ptr
= L
"alt-page-up";
998 ptr
= L
"alt-page-down";
1010 ptr
= L
"alt-kp-plus";
1012 case GDK_KP_Subtract
:
1013 ptr
= L
"alt-kp-minus";
1015 case GDK_KP_Multiply
:
1016 ptr
= L
"alt-kp-multiply";
1019 ptr
= L
"alt-kp-divide";
1061 case GDK_Cyrillic_ve
:
1064 case GDK_Cyrillic_a
:
1067 case GDK_Cyrillic_tse
:
1070 case GDK_Cyrillic_de
:
1073 case GDK_Cyrillic_ie
:
1076 case GDK_Cyrillic_ef
:
1079 case GDK_Cyrillic_ghe
:
1082 case GDK_Cyrillic_i
:
1085 case GDK_Cyrillic_shorti
:
1088 case GDK_Cyrillic_ka
:
1091 case GDK_Cyrillic_el
:
1094 case GDK_Cyrillic_em
:
1097 case GDK_Cyrillic_en
:
1100 case GDK_Cyrillic_o
:
1103 case GDK_Cyrillic_pe
:
1106 case GDK_Cyrillic_ya
:
1109 case GDK_Cyrillic_er
:
1112 case GDK_Cyrillic_es
:
1115 case GDK_Cyrillic_te
:
1118 case GDK_Cyrillic_softsign
:
1121 case GDK_Cyrillic_yeru
:
1124 case GDK_Cyrillic_ze
:
1127 case GDK_Cyrillic_sha
:
1130 case GDK_Cyrillic_e
:
1133 case GDK_Cyrillic_shcha
:
1136 case GDK_Cyrillic_che
:
1142 char c
= event
->keyval
& 0xdf;
1227 switch (event
->keyval
) {
1232 ptr
= L
"cursor-down";
1235 ptr
= L
"cursor-left";
1238 ptr
= L
"cursor-right";
1258 case GDK_KP_Subtract
:
1261 case GDK_KP_Multiply
:
1262 ptr
= L
"kp-multiply";
1319 case GDK_ISO_Left_Tab
:
1328 /* if there is a pending char in im_char, use it */
1329 if (ptr
== NULL
&& im_char
[0] != L
'\0')
1332 /* finally process */
1334 mp_process_event(MPDM_S(ptr
));
1336 /* delete the pending char */
1339 if (mp_exit_requested
)
1342 if (mp_keypress_throttle(1))
1343 gtk_drv_paint(mp_active(), 1);
1349 static gint
button_press_event(GtkWidget
* widget
, GdkEventButton
* event
,
1351 /* 'button_press_event' handler (mouse buttons) */
1354 wchar_t *ptr
= NULL
;
1358 /* mouse instant positioning */
1359 x
= ((int) event
->x
) / font_width
;
1360 y
= ((int) event
->y
) / font_height
;
1362 mpdm_hset_s(mp
, L
"mouse_x", MPDM_I(x
));
1363 mpdm_hset_s(mp
, L
"mouse_y", MPDM_I(y
));
1365 switch (event
->button
) {
1367 ptr
= L
"mouse-left-button";
1370 ptr
= L
"mouse-middle-button";
1373 ptr
= L
"mouse-right-button";
1376 ptr
= L
"mouse-wheel-up";
1379 ptr
= L
"mouse-wheel-down";
1384 mp_process_event(MPDM_S(ptr
));
1392 static gint
button_release_event(GtkWidget
* widget
,
1393 GdkEventButton
* event
, gpointer data
)
1394 /* 'button_release_event' handle (mouse buttons) */
1402 static gint
motion_notify_event(GtkWidget
* widget
, GdkEventMotion
* event
,
1404 /* 'motion_notify_event' handler (mouse movement) */
1412 /* mouse dragging */
1413 x
= ((int) event
->x
) / font_width
;
1414 y
= ((int) event
->y
) / font_height
;
1416 if (ox
!= x
&& oy
!= y
) {
1417 mpdm_hset_s(mp
, L
"mouse_to_x", MPDM_I(x
));
1418 mpdm_hset_s(mp
, L
"mouse_to_y", MPDM_I(y
));
1420 mp_process_event(MPDM_LS(L
"mouse-drag"));
1421 gtk_drv_paint(mp_active(), 1);
1429 static void drag_data_received(GtkWidget
* widget
, GdkDragContext
* dc
,
1430 gint x
, gint y
, GtkSelectionData
* data
,
1431 guint info
, guint time
)
1432 /* 'drag_data_received' handler */
1434 printf("drag_data_received (unsupported)\n");
1438 /** clipboard functions **/
1440 static void commit(GtkIMContext
* i
, char *str
, gpointer u
)
1441 /* 'commit' handler */
1445 wstr
= (wchar_t *) g_convert(str
, -1,
1446 "WCHAR_T", "UTF-8", NULL
, NULL
, NULL
);
1455 static void realize(GtkWidget
* widget
)
1456 /* 'realize' handler */
1458 im
= gtk_im_multicontext_new();
1459 g_signal_connect(im
, "commit", G_CALLBACK(commit
), NULL
);
1460 gtk_im_context_set_client_window(im
, gtk_widget_get_window(widget
));
1464 static gint
expose_event(GtkWidget
* widget
, GdkEventExpose
* event
)
1465 /* 'expose_event' handler */
1473 static gint
configure_event(GtkWidget
* widget
, GdkEventConfigure
* event
)
1474 /* 'configure_event' handler */
1476 static GdkEventConfigure o
;
1478 if (memcmp(&o
, event
, sizeof(o
)) == 0)
1481 memcpy(&o
, event
, sizeof(o
));
1483 update_window_size();
1490 static gint
selection_clear_event(GtkWidget
* widget
,
1491 GdkEventSelection
* event
, gpointer data
)
1492 /* 'selection_clear_event' handler */
1500 static void selection_get(GtkWidget
* widget
,
1501 GtkSelectionData
* sel
, guint info
, guint tm
)
1502 /* 'selection_get' handler */
1511 /* gets the clipboard and joins */
1512 d
= mpdm_hget_s(mp
, L
"clipboard");
1514 if (mpdm_size(d
) == 0)
1517 d
= mpdm_ref(mpdm_join_s(d
, L
"\n"));
1519 /* convert to current locale */
1520 ptr
= (unsigned char *) mpdm_wcstombs(d
->data
, &s
);
1522 /* pastes into primary selection */
1523 gtk_selection_data_set(sel
, GDK_SELECTION_TYPE_STRING
, 8, ptr
,
1532 static void selection_received(GtkWidget
* widget
,
1533 GtkSelectionData
* sel
, gpointer data
)
1534 /* 'selection_received' handler */
1538 if (gtk_selection_data_get_data(sel
) != NULL
) {
1540 wchar_t *wptr
= utf8_to_wcs((char *) gtk_selection_data_get_data(sel
));
1544 /* split and set as the clipboard */
1545 mpdm_hset_s(mp
, L
"clipboard", mpdm_split_s(d
, L
"\n"));
1546 mpdm_hset_s(mp
, L
"clipboard_vertical", MPDM_I(0));
1548 /* wait no more for the selection */
1549 wait_for_selection
= 0;
1552 wait_for_selection
= -1;
1556 static mpdm_t
gtk_drv_clip_to_sys(mpdm_t a
, mpdm_t ctxt
)
1557 /* driver-dependent mp to system clipboard */
1559 got_selection
= gtk_selection_owner_set(area
,
1560 GDK_SELECTION_PRIMARY
,
1567 static mpdm_t
gtk_drv_sys_to_clip(mpdm_t a
, mpdm_t ctxt
)
1568 /* driver-dependent system to mp clipboard */
1570 if (!got_selection
) {
1572 char *formats
[] = { "UTF8_STRING", "STRING", NULL
};
1574 for (n
= 0; formats
[n
] != NULL
; n
++) {
1576 /* triggers a selection capture */
1577 if (gtk_selection_convert(area
, GDK_SELECTION_PRIMARY
,
1578 gdk_atom_intern(formats
[n
], FALSE
),
1579 GDK_CURRENT_TIME
)) {
1581 /* processes the pending events
1582 (i.e., the 'selection_received' handler) */
1583 wait_for_selection
= 1;
1585 while (wait_for_selection
== 1)
1586 gtk_main_iteration();
1588 if (!wait_for_selection
)
1598 /** interface functions **/
1600 static void clicked_ok(GtkWidget
* widget
, gpointer data
)
1601 /* 'clicked_on' signal handler (for gtk_drv_form) */
1605 for (n
= 0; n
< mpdm_size(form_args
); n
++) {
1606 GtkWidget
*widget
= form_widgets
[n
];
1607 mpdm_t w
= mpdm_aget(form_args
, n
);
1608 wchar_t *wptr
= mpdm_string(mpdm_hget_s(w
, L
"type"));
1611 /* if there is already a value there, if was
1612 previously set from a callback */
1613 if (mpdm_aget(form_values
, n
) != NULL
)
1616 if (wcscmp(wptr
, L
"text") == 0 || wcscmp(wptr
, L
"password") == 0) {
1618 GtkWidget
*gw
= widget
;
1621 if (wcscmp(wptr
, L
"text") == 0)
1622 gw
= GTK_COMBO(widget
)->entry
;
1625 gtk_editable_get_chars(GTK_EDITABLE(gw
), 0, -1)) != NULL
1626 && (wptr
= utf8_to_wcs(ptr
)) != NULL
) {
1634 /* if it has history, fill it */
1635 if ((h
= mpdm_hget_s(w
, L
"history")) != NULL
&&
1636 v
!= NULL
&& mpdm_cmp_s(v
, L
"") != 0) {
1637 h
= mp_get_history(h
);
1639 if (mpdm_cmp(v
, mpdm_aget(h
, -1)) != 0)
1646 if (wcscmp(wptr
, L
"checkbox") == 0) {
1647 v
= MPDM_I(gtk_toggle_button_get_active
1648 (GTK_TOGGLE_BUTTON(widget
)));
1651 if (wcscmp(wptr
, L
"list") == 0) {
1652 GtkWidget
*list
= gtk_bin_get_child(GTK_BIN(widget
));
1653 GtkTreeSelection
*selection
=
1654 gtk_tree_view_get_selection(GTK_TREE_VIEW(list
));
1656 gtk_tree_selection_get_selected_rows(selection
, NULL
);
1657 GtkTreePath
*path
= selected
->data
;
1659 v
= MPDM_I(gtk_tree_path_get_indices(path
)[0]);
1660 gtk_tree_path_free(path
);
1661 g_list_free(selected
);
1665 mpdm_aset(form_values
, v
, n
);
1670 static gint
timer_callback(gpointer data
)
1672 mpdm_void(mpdm_exec(timer_func
, NULL
, NULL
));
1679 static void build_form_data(mpdm_t widget_list
)
1680 /* builds the necessary information for a list of widgets */
1682 mpdm_unref(form_args
);
1683 form_args
= mpdm_ref(widget_list
);
1685 mpdm_unref(form_values
);
1686 form_values
= widget_list
== NULL
? NULL
:
1687 mpdm_ref(MPDM_A(mpdm_size(form_args
)));
1689 /* resize the widget array */
1690 form_widgets
= (GtkWidget
**) realloc(form_widgets
,
1691 mpdm_size(form_args
) *
1692 sizeof(GtkWidget
*));
1696 /** dialog functions **/
1698 #define DIALOG_BUTTON(l,f) do { GtkWidget * btn; \
1699 ptr = localize(l); btn = gtk_button_new_with_label(ptr); \
1700 g_signal_connect_swapped(G_OBJECT(btn), "clicked", \
1701 G_CALLBACK(f), G_OBJECT(dlg)); \
1702 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), \
1703 btn, TRUE, TRUE, 0); \
1707 static mpdm_t
gtk_drv_alert(mpdm_t a
, mpdm_t ctxt
)
1708 /* alert driver function */
1713 build_form_data(NULL
);
1715 /* 1# arg: prompt */
1716 if ((ptr
= v_to_utf8(mpdm_aget(a
, 0))) == NULL
)
1719 dlg
= gtk_message_dialog_new(GTK_WINDOW(window
), GTK_DIALOG_MODAL
,
1720 GTK_MESSAGE_WARNING
, GTK_BUTTONS_OK
, "%s", ptr
);
1721 gtk_window_set_title(GTK_WINDOW(dlg
), "mp " VERSION
);
1724 gtk_dialog_run(GTK_DIALOG(dlg
));
1725 gtk_widget_destroy(dlg
);
1731 static mpdm_t
gtk_drv_confirm(mpdm_t a
, mpdm_t ctxt
)
1732 /* confirm driver function */
1738 build_form_data(NULL
);
1740 /* 1# arg: prompt */
1741 if ((ptr
= v_to_utf8(mpdm_aget(a
, 0))) == NULL
)
1744 dlg
= gtk_message_dialog_new(GTK_WINDOW(window
), GTK_DIALOG_MODAL
,
1745 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
,
1747 gtk_window_set_title(GTK_WINDOW(dlg
), "mp " VERSION
);
1750 gtk_dialog_add_button(GTK_DIALOG(dlg
), GTK_STOCK_YES
, 1);
1751 gtk_dialog_add_button(GTK_DIALOG(dlg
), GTK_STOCK_NO
, 2);
1752 gtk_dialog_add_button(GTK_DIALOG(dlg
), GTK_STOCK_CANCEL
, 0);
1754 response
= gtk_dialog_run(GTK_DIALOG(dlg
));
1755 gtk_widget_destroy(dlg
);
1757 if (response
== GTK_RESPONSE_DELETE_EVENT
)
1760 return MPDM_I(response
);
1764 static mpdm_t
gtk_drv_form(mpdm_t a
, mpdm_t ctxt
)
1765 /* 'form' driver function */
1769 GtkWidget
*content_area
;
1773 /* first argument: list of widgets */
1774 build_form_data(mpdm_aget(a
, 0));
1776 dlg
= gtk_dialog_new_with_buttons("mp " VERSION
, GTK_WINDOW(window
),
1778 GTK_DIALOG_NO_SEPARATOR
,
1780 GTK_RESPONSE_CANCEL
, GTK_STOCK_OK
,
1781 GTK_RESPONSE_OK
, NULL
);
1782 gtk_dialog_set_default_response(GTK_DIALOG(dlg
), GTK_RESPONSE_OK
);
1783 gtk_container_set_border_width(GTK_CONTAINER(dlg
), 5);
1785 content_area
= gtk_dialog_get_content_area(GTK_DIALOG(dlg
));
1786 gtk_box_set_spacing(GTK_BOX(content_area
), 2);
1788 table
= gtk_table_new(mpdm_size(a
), 2, FALSE
);
1789 gtk_container_set_border_width(GTK_CONTAINER(table
), 5);
1790 gtk_table_set_col_spacings(GTK_TABLE(table
), 12);
1791 gtk_table_set_row_spacings(GTK_TABLE(table
), 6);
1793 for (n
= 0; n
< mpdm_size(form_args
); n
++) {
1794 mpdm_t w
= mpdm_aget(form_args
, n
);
1795 GtkWidget
*widget
= NULL
;
1801 type
= mpdm_string(mpdm_hget_s(w
, L
"type"));
1803 if ((t
= mpdm_hget_s(w
, L
"label")) != NULL
) {
1806 if ((ptr
= v_to_utf8(mpdm_gettext(t
))) != NULL
) {
1807 label
= gtk_label_new(ptr
);
1808 gtk_misc_set_alignment(GTK_MISC(label
), 0, .5);
1810 gtk_table_attach_defaults(GTK_TABLE(table
),
1811 label
, 0, wcscmp(type
,
1813 0 ? 2 : 1, n
, n
+ 1);
1821 t
= mpdm_hget_s(w
, L
"value");
1823 if (wcscmp(type
, L
"text") == 0) {
1824 GList
*combo_items
= NULL
;
1827 widget
= gtk_combo_new();
1828 gtk_widget_set_size_request(widget
, 300, -1);
1829 gtk_combo_set_use_arrows_always(GTK_COMBO(widget
), TRUE
);
1830 gtk_combo_set_case_sensitive(GTK_COMBO(widget
), TRUE
);
1831 gtk_entry_set_activates_default(GTK_ENTRY
1832 (GTK_COMBO(widget
)->entry
),
1835 if ((h
= mpdm_hget_s(w
, L
"history")) != NULL
) {
1838 /* has history; fill it */
1839 h
= mp_get_history(h
);
1841 for (i
= 0; i
< mpdm_size(h
); i
++) {
1842 ptr
= v_to_utf8(mpdm_aget(h
, i
));
1844 combo_items
= g_list_prepend(combo_items
, ptr
);
1851 combo_items
= g_list_prepend(combo_items
, ptr
);
1854 gtk_combo_set_popdown_strings(GTK_COMBO(widget
), combo_items
);
1855 g_list_free(combo_items
);
1858 if (wcscmp(type
, L
"password") == 0) {
1859 widget
= gtk_entry_new();
1860 gtk_widget_set_size_request(widget
, 300, -1);
1861 gtk_entry_set_visibility(GTK_ENTRY(widget
), FALSE
);
1864 if (wcscmp(type
, L
"checkbox") == 0) {
1865 widget
= gtk_check_button_new();
1867 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
),
1868 mpdm_ival(t
) ? TRUE
: FALSE
);
1871 if (wcscmp(type
, L
"list") == 0) {
1873 GtkListStore
*list_store
;
1874 GtkCellRenderer
*renderer
;
1875 GtkTreeViewColumn
*column
;
1880 if ((i
= 450 / mpdm_size(form_args
)) < 100)
1883 widget
= gtk_scrolled_window_new(NULL
, NULL
);
1884 gtk_widget_set_size_request(widget
, 500, i
);
1885 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget
),
1887 GTK_POLICY_AUTOMATIC
);
1888 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW
1889 (widget
), GTK_SHADOW_IN
);
1891 list_store
= gtk_list_store_new(1, G_TYPE_STRING
);
1893 gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store
));
1894 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list
), FALSE
);
1895 renderer
= gtk_cell_renderer_text_new();
1896 column
= gtk_tree_view_column_new_with_attributes("", renderer
,
1899 gtk_tree_view_append_column(GTK_TREE_VIEW(list
), column
);
1900 gtk_container_add(GTK_CONTAINER(widget
), list
);
1902 l
= mpdm_hget_s(w
, L
"list");
1904 for (i
= 0; i
< mpdm_size(l
); i
++) {
1905 if ((ptr
= v_to_utf8(mpdm_aget(l
, i
))) != NULL
) {
1907 gtk_list_store_append(list_store
, &iter
);
1908 gtk_list_store_set(list_store
, &iter
, 0, ptr
, -1);
1913 /* initial position */
1916 path
= gtk_tree_path_new_from_indices(i
, -1);
1917 gtk_tree_view_set_cursor(GTK_TREE_VIEW(list
), path
, NULL
,
1919 gtk_tree_path_free(path
);
1921 g_signal_connect_swapped(G_OBJECT(list
), "row-activated",
1923 (gtk_window_activate_default
), dlg
);
1926 if (widget
!= NULL
) {
1927 form_widgets
[n
] = widget
;
1928 gtk_table_attach_defaults(GTK_TABLE(table
),
1929 widget
, col
, 2, n
, n
+ 1);
1933 gtk_widget_show_all(table
);
1935 gtk_box_pack_start(GTK_BOX(content_area
), table
, TRUE
, TRUE
, 0);
1937 if (gtk_dialog_run(GTK_DIALOG(dlg
)) == GTK_RESPONSE_OK
) {
1938 clicked_ok(NULL
, NULL
);
1941 gtk_widget_destroy(dlg
);
1947 static mpdm_t
run_filechooser(mpdm_t a
, gboolean save
)
1948 /* openfile driver function */
1955 /* 1# arg: prompt */
1956 if ((ptr
= v_to_utf8(mpdm_aget(a
, 0))) == NULL
)
1960 dlg
= gtk_file_chooser_dialog_new(ptr
, GTK_WINDOW(window
),
1961 GTK_FILE_CHOOSER_ACTION_OPEN
,
1963 GTK_RESPONSE_CANCEL
,
1964 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
1968 dlg
= gtk_file_chooser_dialog_new(ptr
, GTK_WINDOW(window
),
1969 GTK_FILE_CHOOSER_ACTION_SAVE
,
1971 GTK_STOCK_CANCEL
, GTK_STOCK_OK
,
1972 GTK_RESPONSE_OK
, NULL
);
1973 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER
1978 build_form_data(NULL
);
1980 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dlg
), TRUE
);
1981 response
= gtk_dialog_run(GTK_DIALOG(dlg
));
1983 if (response
== GTK_RESPONSE_OK
) {
1988 filename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg
));
1989 utf8name
= g_filename_to_utf8(filename
, -1, NULL
, NULL
, NULL
);
1991 wfilename
= utf8_to_wcs(utf8name
);
1993 ret
= MPDM_S(wfilename
);
1996 gtk_widget_destroy(dlg
);
2002 static mpdm_t
gtk_drv_openfile(mpdm_t a
, mpdm_t ctxt
)
2003 /* openfile driver function */
2005 return run_filechooser(a
, FALSE
);
2009 static mpdm_t
gtk_drv_savefile(mpdm_t a
, mpdm_t ctxt
)
2010 /* savefile driver function */
2012 return run_filechooser(a
, TRUE
);
2016 static mpdm_t
gtk_drv_update_ui(mpdm_t a
, mpdm_t ctxt
)
2028 static mpdm_t
gtk_drv_timer(mpdm_t a
, mpdm_t ctxt
)
2030 static guint prev
= 0;
2031 int msecs
= mpdm_ival(mpdm_aget(a
, 0));
2032 mpdm_t func
= mpdm_aget(a
, 1);
2034 /* previously defined one? remove */
2035 if (timer_func
!= NULL
)
2036 g_source_remove(prev
);
2038 /* if msecs and func are set, program timer */
2039 if (msecs
> 0 && func
!= NULL
)
2040 prev
= g_timeout_add(msecs
, timer_callback
, NULL
);
2043 mpdm_unref(timer_func
);
2050 static mpdm_t
gtk_drv_busy(mpdm_t a
, mpdm_t ctxt
)
2052 int onoff
= mpdm_ival(mpdm_aget(a
, 0));
2054 gdk_window_set_cursor(gtk_widget_get_window(window
),
2055 gdk_cursor_new(onoff
? GDK_WATCH
:
2058 while (gtk_events_pending())
2059 gtk_main_iteration();
2065 static mpdm_t
gtk_drv_main_loop(mpdm_t a
, mpdm_t ctxt
)
2068 if (!mp_exit_requested
) {
2069 gtk_drv_paint(mp_active(), 0);
2078 static mpdm_t
gtk_drv_shutdown(mpdm_t a
, mpdm_t ctxt
)
2083 if ((v
= mpdm_hget_s(mp
, L
"exit_message")) != NULL
) {
2084 mpdm_write_wcs(stdout
, mpdm_string(v
));
2092 static void register_functions(void)
2096 drv
= mpdm_hget_s(mp
, L
"drv");
2097 mpdm_hset_s(drv
, L
"main_loop", MPDM_X(gtk_drv_main_loop
));
2098 mpdm_hset_s(drv
, L
"shutdown", MPDM_X(gtk_drv_shutdown
));
2099 mpdm_hset_s(drv
, L
"clip_to_sys", MPDM_X(gtk_drv_clip_to_sys
));
2100 mpdm_hset_s(drv
, L
"sys_to_clip", MPDM_X(gtk_drv_sys_to_clip
));
2101 mpdm_hset_s(drv
, L
"update_ui", MPDM_X(gtk_drv_update_ui
));
2102 mpdm_hset_s(drv
, L
"timer", MPDM_X(gtk_drv_timer
));
2103 mpdm_hset_s(drv
, L
"busy", MPDM_X(gtk_drv_busy
));
2104 mpdm_hset_s(drv
, L
"alert", MPDM_X(gtk_drv_alert
));
2105 mpdm_hset_s(drv
, L
"confirm", MPDM_X(gtk_drv_confirm
));
2106 mpdm_hset_s(drv
, L
"openfile", MPDM_X(gtk_drv_openfile
));
2107 mpdm_hset_s(drv
, L
"savefile", MPDM_X(gtk_drv_savefile
));
2108 mpdm_hset_s(drv
, L
"form", MPDM_X(gtk_drv_form
));
2112 static mpdm_t
gtk_drv_startup(mpdm_t a
, mpdm_t ctxt
)
2113 /* driver initialization */
2122 GtkTargetEntry targets
[] = {
2123 {"text/plain", 0, 0},
2124 {"text/uri-list", 0, 1}
2127 register_functions();
2129 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
2131 gtk_window_set_title(GTK_WINDOW(window
), "mp " VERSION
);
2133 /* get real screen and pick a usable size for the main area */
2134 screen
= gtk_window_get_screen(GTK_WINDOW(window
));
2135 if (gdk_screen_get_n_monitors(screen
) > 1) {
2136 GdkRectangle monitor_one_size
;
2137 gdk_screen_get_monitor_geometry(screen
, 0, &monitor_one_size
);
2139 w
= (monitor_one_size
.width
* 3) / 4;
2140 h
= (monitor_one_size
.height
* 2) / 3;
2142 w
= (gdk_screen_get_width(screen
) * 3) / 4;
2143 h
= (gdk_screen_get_height(screen
) * 2) / 3;
2146 g_signal_connect(G_OBJECT(window
), "delete_event",
2147 G_CALLBACK(delete_event
), NULL
);
2149 g_signal_connect(G_OBJECT(window
), "destroy",
2150 G_CALLBACK(destroy
), NULL
);
2153 file_tabs
= gtk_notebook_new();
2154 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(file_tabs
), GTK_POS_TOP
);
2155 GTK_WIDGET_UNSET_FLAGS(file_tabs
, GTK_CAN_FOCUS
);
2156 gtk_notebook_set_scrollable(GTK_NOTEBOOK(file_tabs
), 1);
2158 vbox
= gtk_vbox_new(FALSE
, 2);
2159 gtk_container_add(GTK_CONTAINER(window
), vbox
);
2163 hbox
= gtk_hbox_new(FALSE
, 0);
2164 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
2165 gtk_box_pack_start(GTK_BOX(hbox
), menu_bar
, FALSE
, FALSE
, 0);
2166 gtk_box_pack_start(GTK_BOX(hbox
), file_tabs
, TRUE
, TRUE
, 0);
2168 gtk_notebook_popup_enable(GTK_NOTEBOOK(file_tabs
));
2170 /* horizontal box holding the text and the scrollbar */
2171 hbox
= gtk_hbox_new(FALSE
, 2);
2172 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, TRUE
, TRUE
, 0);
2174 /* the Minimum Profit area */
2175 area
= gtk_drawing_area_new();
2176 gtk_box_pack_start(GTK_BOX(hbox
), area
, TRUE
, TRUE
, 0);
2177 gtk_widget_set_size_request(GTK_WIDGET(area
), w
, h
);
2178 gtk_widget_set_events(GTK_WIDGET(area
), GDK_BUTTON_PRESS_MASK
|
2179 GDK_BUTTON_RELEASE_MASK
| GDK_POINTER_MOTION_MASK
2180 | GDK_LEAVE_NOTIFY_MASK
);
2182 gtk_widget_set_double_buffered(area
, FALSE
);
2184 g_signal_connect(G_OBJECT(area
), "configure_event",
2185 G_CALLBACK(configure_event
), NULL
);
2187 g_signal_connect(G_OBJECT(area
), "expose_event",
2188 G_CALLBACK(expose_event
), NULL
);
2190 g_signal_connect(G_OBJECT(area
), "realize", G_CALLBACK(realize
), NULL
);
2192 g_signal_connect(G_OBJECT(window
), "key_press_event",
2193 G_CALLBACK(key_press_event
), NULL
);
2195 g_signal_connect(G_OBJECT(window
), "key_release_event",
2196 G_CALLBACK(key_release_event
), NULL
);
2198 g_signal_connect(G_OBJECT(area
), "button_press_event",
2199 G_CALLBACK(button_press_event
), NULL
);
2201 g_signal_connect(G_OBJECT(area
), "button_release_event",
2202 G_CALLBACK(button_release_event
), NULL
);
2204 g_signal_connect(G_OBJECT(area
), "motion_notify_event",
2205 G_CALLBACK(motion_notify_event
), NULL
);
2207 g_signal_connect(G_OBJECT(area
), "selection_clear_event",
2208 G_CALLBACK(selection_clear_event
), NULL
);
2210 g_signal_connect(G_OBJECT(area
), "selection_get",
2211 G_CALLBACK(selection_get
), NULL
);
2213 g_signal_connect(G_OBJECT(area
), "selection_received",
2214 G_CALLBACK(selection_received
), NULL
);
2216 g_signal_connect(G_OBJECT(area
), "scroll_event",
2217 G_CALLBACK(scroll_event
), NULL
);
2219 gtk_drag_dest_set(area
, GTK_DEST_DEFAULT_ALL
, targets
,
2220 sizeof(targets
) / sizeof(GtkTargetEntry
),
2222 g_signal_connect(G_OBJECT(area
), "drag_data_received",
2223 G_CALLBACK(drag_data_received
), NULL
);
2225 gtk_selection_add_target(area
, GDK_SELECTION_PRIMARY
,
2226 GDK_SELECTION_TYPE_STRING
, 1);
2228 g_signal_connect(G_OBJECT(file_tabs
), "switch_page",
2229 G_CALLBACK(switch_page
), NULL
);
2232 scrollbar
= gtk_vscrollbar_new(NULL
);
2233 gtk_box_pack_start(GTK_BOX(hbox
), scrollbar
, FALSE
, FALSE
, 0);
2235 g_signal_connect(G_OBJECT
2236 (gtk_range_get_adjustment(GTK_RANGE(scrollbar
))),
2237 "value_changed", G_CALLBACK(value_changed
), NULL
);
2239 /* the status bar */
2240 status
= gtk_label_new("mp " VERSION
);
2241 gtk_box_pack_start(GTK_BOX(vbox
), status
, FALSE
, FALSE
, 0);
2242 gtk_misc_set_alignment(GTK_MISC(status
), 0, 0.5);
2243 gtk_label_set_justify(GTK_LABEL(status
), GTK_JUSTIFY_LEFT
);
2245 gtk_widget_show_all(window
);
2247 /* set application icon */
2248 pixmap
= gdk_pixmap_create_from_xpm_d(window
->window
,
2249 &mask
, NULL
, mp_xpm
);
2250 gdk_window_set_icon(window
->window
, NULL
, pixmap
, mask
);
2254 if ((v
= mpdm_hget_s(mp
, L
"config")) != NULL
&&
2255 mpdm_ival(mpdm_hget_s(v
, L
"maximize")) > 0)
2262 int gtk_drv_detect(int *argc
, char ***argv
)
2267 for (n
= 0; n
< *argc
; n
++) {
2268 if (strcmp(argv
[0][n
], "-txt") == 0 ||
2269 strcmp(argv
[0][n
], "-h") == 0)
2273 if (!gtk_init_check(argc
, argv
))
2276 drv
= mpdm_hget_s(mp
, L
"drv");
2277 mpdm_hset_s(drv
, L
"id", MPDM_LS(L
"gtk"));
2278 mpdm_hset_s(drv
, L
"startup", MPDM_X(gtk_drv_startup
));
2283 #endif /* CONFOPT_GTK */