2 Copyright (c) 2001, Loki software, inc.
\r
5 Redistribution and use in source and binary forms, with or without modification,
\r
6 are permitted provided that the following conditions are met:
\r
8 Redistributions of source code must retain the above copyright notice, this list
\r
9 of conditions and the following disclaimer.
\r
11 Redistributions in binary form must reproduce the above copyright notice, this
\r
12 list of conditions and the following disclaimer in the documentation and/or
\r
13 other materials provided with the distribution.
\r
15 Neither the name of Loki software nor the names of its contributors may be used
\r
16 to endorse or promote products derived from this software without specific prior
\r
17 written permission.
\r
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
\r
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
\r
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
\r
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
\r
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
\r
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
\r
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
\r
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
\r
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
32 // Small functions to help with GTK
\r
35 #include <gdk/gdkkeysyms.h>
\r
37 #if defined (__linux__) || defined (__APPLE__)
\r
41 #include <gtk/gtk.h>
\r
45 #include <gdk/gdkwin32.h>
\r
46 #define WIN32_LEAN_AND_MEAN
\r
47 #include <windows.h>
\r
59 // =============================================================================
\r
62 // NOTE TTimo window position saving has always been tricky
\r
63 // it doesn't work the same between win32 and linux .. see below that code is fairly different
\r
64 // it's also very poorly done, the save calls are a bit randomly disctributed in the OnDestroy
\r
66 void save_window_pos (GtkWidget *wnd, window_position_t& pos)
\r
68 if ((wnd == NULL) || (wnd->window == NULL))
\r
71 get_window_pos(wnd, &pos.x, &pos.y);
\r
73 pos.w = wnd->allocation.width;
\r
74 pos.h = wnd->allocation.height;
\r
76 #ifdef DBG_WINDOWPOS
\r
77 //Sys_Printf("save_window_pos 'Window %s'\n",buf);
\r
82 void win32_get_window_pos(GtkWidget *widget, gint *x, gint *y)
\r
84 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=913
\r
85 if ( g_PrefsDlg.m_bStartOnPrimMon ) {
\r
88 HWND xwnd = (HWND)GDK_WINDOW_HWND (widget->window);
\r
89 const GdkRectangle primaryMonitorRect = g_pParentWnd->GetPrimaryMonitorRect();
\r
91 GetClientRect(xwnd,&rc);
\r
94 ClientToScreen(xwnd,&point);
\r
99 *x=max(*x,-widget->allocation.width+10);
\r
100 *x=min(*x,primaryMonitorRect.width-10);
\r
101 *y=max(*y,-widget->allocation.height+10);
\r
102 *y=min(*y,primaryMonitorRect.height-10);
\r
104 // this is the same as the unix version of get_window_pos
\r
105 gdk_window_get_root_origin (widget->window, x, y);
\r
107 #ifdef DBG_WINDOWPOS
\r
108 Sys_Printf("win32_get_window_pos %p %d,%d\n",widget,*x,*y);
\r
113 void load_window_pos (GtkWidget *wnd, window_position_t& pos)
\r
116 const GdkRectangle primaryMonitorRect = g_pParentWnd->GetPrimaryMonitorRect();
\r
118 if(pos.x < primaryMonitorRect.x
\r
119 || pos.y < primaryMonitorRect.y
\r
120 || pos.x > primaryMonitorRect.x + primaryMonitorRect.width
\r
121 || pos.y > primaryMonitorRect.y + primaryMonitorRect.height)
\r
122 gtk_window_set_position(GTK_WINDOW(wnd), GTK_WIN_POS_CENTER_ON_PARENT);
\r
124 // FIXME: not multihead safe
\r
127 || pos.x > gdk_screen_width ()
\r
128 || pos.y > gdk_screen_height ())
\r
129 gtk_window_set_position(GTK_WINDOW(wnd), GTK_WIN_POS_CENTER_ON_PARENT);
\r
132 gtk_window_move(GTK_WINDOW(wnd), pos.x, pos.y);
\r
134 gtk_window_set_default_size (GTK_WINDOW (wnd), pos.w, pos.h);
\r
135 #ifdef DBG_WINDOWPOS
\r
136 Sys_Printf("load_window_pos %p 'Window,%s'\n",wnd,windowData);
\r
140 gint widget_delete_hide (GtkWidget *widget)
\r
142 gtk_widget_hide (widget);
\r
148 // Thanks to Mercury, Fingolfin - ETG
\r
149 int readLongLE(FILE *file, unsigned long *m_bytesRead, int *value)
\r
152 int len = fread(buf, 4, 1, file);
\r
157 *value = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;
\r
161 short readShortLE(FILE *file, unsigned long *m_bytesRead, short unsigned *value)
\r
164 int len = fread(buf, 2, 1, file);
\r
169 *value = buf[0] | buf[1] << 8;
\r
173 unsigned char *load_bitmap_file (const char* filename, guint16 *width, guint16 *height)
\r
175 int bmWidth, bmHeight;
\r
176 short unsigned bmPlanes, bmBitsPixel;
\r
178 unsigned char rgbBlue;
\r
179 unsigned char rgbGreen;
\r
180 unsigned char rgbRed;
\r
181 unsigned char rgbReserved;
\r
183 unsigned char m1,m2;
\r
185 short unsigned res1,res2;
\r
186 int filesize, pixoff;
\r
187 int bmisize, compression;
\r
188 int xscale, yscale;
\r
189 int colors, impcol;
\r
190 unsigned long m_bytesRead = 0;
\r
191 unsigned char *imagebits = NULL;
\r
194 *width = *height = 0;
\r
196 fp = fopen(filename,"rb");
\r
203 rc = fread(&m1, 1, 1, fp);
\r
211 rc = fread(&m2, 1, 1, fp);
\r
213 if ((m1!='B') || (m2!='M'))
\r
219 if (readLongLE(fp,&m_bytesRead,&filesize)) {
\r
224 if (readShortLE(fp,&m_bytesRead,&res1)) {
\r
229 if (readShortLE(fp,&m_bytesRead,&res2)) {
\r
234 if (readLongLE(fp,&m_bytesRead,&pixoff)) {
\r
239 if (readLongLE(fp,&m_bytesRead,&bmisize)) {
\r
244 if (readLongLE(fp,&m_bytesRead,&bmWidth)) {
\r
249 if (readLongLE(fp,&m_bytesRead,&bmHeight)) {
\r
254 if (readShortLE(fp,&m_bytesRead,&bmPlanes)) {
\r
259 if (readShortLE(fp,&m_bytesRead,&bmBitsPixel)) {
\r
264 if (readLongLE(fp,&m_bytesRead,&compression)) {
\r
269 if (readLongLE(fp,&m_bytesRead,&sizeimage)) {
\r
274 if (readLongLE(fp,&m_bytesRead,&xscale)) {
\r
279 if (readLongLE(fp,&m_bytesRead,&yscale)) {
\r
284 if (readLongLE(fp,&m_bytesRead,&colors)) {
\r
289 if (readLongLE(fp,&m_bytesRead,&impcol)) {
\r
295 colors = 1 << bmBitsPixel;
\r
297 RGBQUAD *colormap = NULL;
\r
298 if (bmBitsPixel != 24)
\r
300 colormap = new RGBQUAD[colors];
\r
301 if (colormap == NULL)
\r
308 for (i = 0; i < colors; i++)
\r
310 unsigned char r ,g, b, dummy;
\r
312 rc = fread(&b, 1, 1, fp);
\r
316 delete [] colormap;
\r
321 rc = fread(&g, 1, 1, fp);
\r
325 delete [] colormap;
\r
330 rc = fread(&r, 1, 1, fp);
\r
334 delete [] colormap;
\r
339 rc = fread(&dummy, 1, 1, fp);
\r
343 delete [] colormap;
\r
348 colormap[i].rgbRed=r;
\r
349 colormap[i].rgbGreen=g;
\r
350 colormap[i].rgbBlue=b;
\r
354 if ((long)m_bytesRead > pixoff)
\r
356 delete [] colormap;
\r
361 while ((long)m_bytesRead < pixoff)
\r
364 fread(&dummy,1,1,fp);
\r
371 // set the output params
\r
372 imagebits = (unsigned char *)malloc(w * h * 3);
\r
373 long row_size = w * 3;
\r
375 if (imagebits != NULL)
\r
379 unsigned char *outbuf = imagebits;
\r
381 long rowOffset = 0;
\r
383 if (compression == 0) // BI_RGB
\r
385 // read rows in reverse order
\r
386 for (row = bmHeight - 1; row >= 0; row--)
\r
388 // which row are we working on?
\r
389 rowOffset = (long unsigned)row * row_size;
\r
391 if (bmBitsPixel == 24)
\r
393 for (int col=0;col<w;col++)
\r
395 long offset = col * 3;
\r
398 if (fread((void *)(pixel),1,3,fp) == 3)
\r
400 // we swap red and blue here
\r
401 *(outbuf + rowOffset + offset + 0) = pixel[2]; // r
\r
402 *(outbuf + rowOffset + offset + 1) = pixel[1]; // g
\r
403 *(outbuf + rowOffset + offset + 2) = pixel[0]; // b
\r
406 m_bytesRead += row_size;
\r
408 // read DWORD padding
\r
409 while ((m_bytesRead - pixoff) & 3)
\r
412 if (fread(&dummy,1,1,fp) != 1)
\r
423 // pixels are packed as 1 , 4 or 8 bit vals. need to unpack them
\r
425 unsigned long mask = (1 << bmBitsPixel) - 1;
\r
426 unsigned char inbyte = 0;
\r
428 for (int col = 0; col < w; col++)
\r
432 // if we need another byte
\r
433 if (bit_count <= 0)
\r
436 if (fread(&inbyte,1,1,fp) != 1)
\r
439 delete [] colormap;
\r
446 // keep track of where we are in the bytes
\r
447 bit_count -= bmBitsPixel;
\r
448 pix = ( inbyte >> bit_count) & mask;
\r
450 // lookup the color from the colormap - stuff it in our buffer
\r
451 // swap red and blue
\r
452 *(outbuf + rowOffset + col * 3 + 2) = colormap[pix].rgbBlue;
\r
453 *(outbuf + rowOffset + col * 3 + 1) = colormap[pix].rgbGreen;
\r
454 *(outbuf + rowOffset + col * 3 + 0) = colormap[pix].rgbRed;
\r
457 // read DWORD padding
\r
458 while ((m_bytesRead - pixoff) & 3)
\r
461 if (fread(&dummy,1,1,fp)!=1)
\r
465 delete [] colormap;
\r
477 unsigned char c, c1 = 0, *pp;
\r
479 pp = outbuf + (bmHeight - 1) * bmWidth * 3;
\r
481 if (bmBitsPixel == 8)
\r
483 while (row < bmHeight)
\r
491 for (i = 0; i < c; x++, i++)
\r
493 *pp = colormap[c1].rgbRed; pp++;
\r
494 *pp = colormap[c1].rgbGreen; pp++;
\r
495 *pp = colormap[c1].rgbBlue; pp++;
\r
500 // c==0x00, escape codes
\r
502 if (c == 0x00) // end of line
\r
506 pp = outbuf + (bmHeight - row - 1) * bmWidth * 3;
\r
508 else if (c == 0x01)
\r
509 break; // end of pic
\r
510 else if (c == 0x02) // delta
\r
516 pp = outbuf + x*3 + (bmHeight - row - 1) * bmWidth * 3;
\r
518 else // absolute mode
\r
520 for (i = 0; i < c; x++, i++)
\r
523 *pp = colormap[c1].rgbRed; pp++;
\r
524 *pp = colormap[c1].rgbGreen; pp++;
\r
525 *pp = colormap[c1].rgbBlue; pp++;
\r
529 getc(fp); // odd length run: read an extra pad byte
\r
534 else if (bmBitsPixel == 4)
\r
536 while (row < bmHeight)
\r
544 for (i = 0; i < c; x++, i++)
\r
546 *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++;
\r
547 *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++;
\r
548 *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++;
\r
553 // c==0x00, escape codes
\r
556 if (c == 0x00) // end of line
\r
560 pp = outbuf + (bmHeight - row - 1) * bmWidth * 3;
\r
562 else if (c == 0x01)
\r
563 break; // end of pic
\r
564 else if (c == 0x02) // delta
\r
570 pp = outbuf + x * 3 + (bmHeight - row - 1) * bmWidth * 3;
\r
572 else // absolute mode
\r
574 for (i = 0; i < c; x++, i++)
\r
578 *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++;
\r
579 *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++;
\r
580 *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++;
\r
583 if (((c & 3) == 1) || ((c & 3) == 2))
\r
584 getc(fp); // odd length run: read an extra pad byte
\r
591 delete [] colormap;
\r
598 void bmp_to_pixmap (const char* filename, GdkPixmap **pixmap, GdkBitmap **mask)
\r
600 guint16 width, height;
\r
601 unsigned char *buf;
\r
602 GdkWindow *window = gdk_get_default_root_window();
\r
603 GdkColormap *colormap;
\r
604 GdkGC* gc = gdk_gc_new (window);
\r
606 bool hasMask = false;
\r
608 *pixmap = *mask = NULL;
\r
609 buf = load_bitmap_file (filename, &width, &height);
\r
613 colormap = gdk_drawable_get_colormap (window);
\r
614 *pixmap = gdk_pixmap_new (window, width, height, -1);
\r
622 for (i = 0; i < height; i++)
\r
624 for (j = 0; j < width; j++)
\r
626 unsigned char *p = &buf[(i * width + j) * 3];
\r
629 pe.c.red = (gushort)(p[0] * 0xFF);
\r
630 pe.c.green = (gushort)(p[1] * 0xFF);
\r
631 pe.c.blue = (gushort)(p[2] * 0xFF);
\r
632 gdk_colormap_alloc_color(colormap, &pe.c, FALSE, TRUE);
\r
633 gdk_gc_set_foreground(gc, &pe.c);
\r
634 gdk_draw_point(*pixmap, gc, j, i);
\r
636 if (p[0] == 0xFF && p[1] == 0x00 && p[2] == 0xFF)
\r
642 *mask = gdk_pixmap_new (window, width, height, 1);
\r
643 gc = gdk_gc_new (*mask);
\r
646 for (i = 0; i < height; i++)
\r
648 for (j = 0; j < width; j++)
\r
650 GdkColor mask_pattern;
\r
652 // pink is transparent
\r
653 if ((buf[(i*width+j)*3] == 0xff) &&
\r
654 (buf[(i*width+j)*3+1] == 0x00) &&
\r
655 (buf[(i*width+j)*3+2] == 0xff))
\r
656 mask_pattern.pixel = 0;
\r
658 mask_pattern.pixel = 1;
\r
660 gdk_gc_set_foreground (gc, &mask_pattern);
\r
661 // possible Win32 Gtk bug here
\r
662 //gdk_draw_point (*mask, gc, j, i);
\r
663 gdk_draw_line (*mask, gc, j, i, j + 1, i);
\r
669 GdkColor mask_pattern;
\r
670 mask_pattern.pixel = 1;
\r
671 gdk_gc_set_foreground (gc, &mask_pattern);
\r
672 gdk_draw_rectangle (*mask, gc, 1, 0, 0, width, height);
\r
678 void load_pixmap (const char* filename, GtkWidget* widget, GdkPixmap **gdkpixmap, GdkBitmap **mask)
\r
682 str = g_strBitmapsPath;
\r
685 bmp_to_pixmap (str.GetBuffer (), gdkpixmap, mask);
\r
686 if (*gdkpixmap == NULL)
\r
688 printf("gdkpixmap was null\n");
\r
689 char *dummy[] = { "1 1 1 1", " c None", " " };
\r
690 printf("calling gdk_pixmap_create_from_xpm_d\n");
\r
691 *gdkpixmap = gdk_pixmap_create_from_xpm_d (gdk_get_default_root_window(), mask, NULL, dummy);
\r
695 // this is the same as above but used by the plugins
\r
696 // GdkPixmap **gdkpixmap, GdkBitmap **mask
\r
697 bool WINAPI load_plugin_bitmap (const char* filename, void **gdkpixmap, void **mask)
\r
701 str = g_strGameToolsPath;
\r
702 str += g_strPluginsDir;
\r
705 bmp_to_pixmap (str.GetBuffer (), (GdkPixmap **)gdkpixmap, (GdkBitmap **)mask);
\r
707 if (*gdkpixmap == NULL)
\r
709 // look in the core plugins
\r
710 str = g_strAppPath;
\r
711 str += g_strPluginsDir;
\r
714 bmp_to_pixmap (str.GetBuffer (), (GdkPixmap **)gdkpixmap, (GdkBitmap **)mask);
\r
716 if (*gdkpixmap == NULL)
\r
719 // look in core modules
\r
720 str = g_strAppPath;
\r
721 str += g_strModulesDir;
\r
724 bmp_to_pixmap (str.GetBuffer (), (GdkPixmap **)gdkpixmap, (GdkBitmap **)mask);
\r
726 if (*gdkpixmap == NULL)
\r
728 char *dummy[] = { "1 1 1 1", " c None", " " };
\r
729 *gdkpixmap = gdk_pixmap_create_from_xpm_d (gdk_get_default_root_window(), (GdkBitmap **)mask, NULL, dummy);
\r
737 // Load a xpm file and return a pixmap widget.
\r
738 GtkWidget* new_pixmap (GtkWidget* widget, char* filename)
\r
740 GdkPixmap *gdkpixmap;
\r
744 load_pixmap (filename, widget, &gdkpixmap, &mask);
\r
745 pixmap = gtk_pixmap_new (gdkpixmap, mask);
\r
747 gdk_drawable_unref (gdkpixmap);
\r
748 gdk_drawable_unref (mask);
\r
753 // =============================================================================
\r
756 GtkWidget* menu_separator (GtkWidget *menu)
\r
758 GtkWidget *menu_item = gtk_menu_item_new ();
\r
759 gtk_menu_append (GTK_MENU (menu), menu_item);
\r
760 gtk_widget_set_sensitive (menu_item, FALSE);
\r
761 gtk_widget_show (menu_item);
\r
765 GtkWidget* menu_tearoff (GtkWidget *menu)
\r
767 GtkWidget *menu_item = gtk_tearoff_menu_item_new ();
\r
768 gtk_menu_append (GTK_MENU (menu), menu_item);
\r
769 // gtk_widget_set_sensitive (menu_item, FALSE); -- controls whether menu is detachable
\r
770 gtk_widget_show (menu_item);
\r
774 GtkWidget* create_sub_menu_with_mnemonic (GtkWidget *bar, gchar *mnemonic)
\r
776 GtkWidget *item, *sub_menu;
\r
778 item = gtk_menu_item_new_with_mnemonic (mnemonic);
\r
779 gtk_widget_show (item);
\r
780 gtk_container_add (GTK_CONTAINER (bar), item);
\r
782 sub_menu = gtk_menu_new ();
\r
783 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), sub_menu);
\r
788 extern void AddMenuItem (GtkWidget* menu, unsigned int id);
\r
790 GtkWidget* create_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id)
\r
794 item = gtk_menu_item_new_with_mnemonic (mnemonic);
\r
796 gtk_widget_show (item);
\r
797 gtk_container_add (GTK_CONTAINER (menu), item);
\r
798 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));
\r
800 AddMenuItem (item, id);
\r
804 GtkWidget* create_check_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id, gboolean active)
\r
808 item = gtk_check_menu_item_new_with_mnemonic(mnemonic);
\r
810 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), active);
\r
811 gtk_widget_show (item);
\r
812 gtk_container_add (GTK_CONTAINER (menu), item);
\r
813 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));
\r
815 AddMenuItem (item, id);
\r
819 GtkWidget* create_radio_menu_item_with_mnemonic (GtkWidget *menu, GtkWidget *last, gchar *mnemonic, GtkSignalFunc func, int id, gboolean state)
\r
822 GSList *group = (GSList*)NULL;
\r
825 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (last));
\r
826 item = gtk_radio_menu_item_new_with_mnemonic (group, mnemonic);
\r
827 gtk_check_menu_item_set_state (GTK_CHECK_MENU_ITEM (item), state);
\r
829 gtk_widget_show (item);
\r
830 gtk_container_add (GTK_CONTAINER (menu), item);
\r
831 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));
\r
833 AddMenuItem (item, id);
\r
837 GtkWidget* create_menu_in_menu_with_mnemonic (GtkWidget *menu, const gchar *mnemonic)
\r
839 GtkWidget *item, *submenu;
\r
841 item = gtk_menu_item_new_with_mnemonic(mnemonic);
\r
842 gtk_widget_show (item);
\r
843 gtk_container_add (GTK_CONTAINER (menu), item);
\r
845 submenu = gtk_menu_new ();
\r
846 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
\r
851 // =============================================================================
\r
854 void dialog_button_callback (GtkWidget *widget, gpointer data)
\r
859 parent = gtk_widget_get_toplevel (widget);
\r
860 loop = (int*)g_object_get_data (G_OBJECT (parent), "loop");
\r
861 ret = (int*)g_object_get_data (G_OBJECT (parent), "ret");
\r
867 gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data)
\r
871 gtk_widget_hide (widget);
\r
872 loop = (int*)g_object_get_data (G_OBJECT (widget), "loop");
\r
878 gint dialog_url_callback (GtkWidget *widget, GdkEvent* event, gpointer data)
\r
880 OpenURL((const char *)g_object_get_data (G_OBJECT (widget), "URL"));
\r
885 int WINAPI gtk_MessageBox (void *parent, const char* lpText, const char* lpCaption, guint32 uType, const char* URL)
\r
887 GtkWidget *window, *w, *vbox, *hbox;
\r
888 GtkAccelGroup *accel;
\r
889 int mode = (uType & MB_TYPEMASK), ret, loop = 1;
\r
891 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
\r
892 gtk_signal_connect (GTK_OBJECT (window), "delete_event",
\r
893 GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
\r
894 gtk_signal_connect (GTK_OBJECT (window), "destroy",
\r
895 GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
\r
896 gtk_window_set_title (GTK_WINDOW (window), lpCaption);
\r
897 gtk_container_border_width (GTK_CONTAINER (window), 10);
\r
898 g_object_set_data (G_OBJECT (window), "loop", &loop);
\r
899 g_object_set_data (G_OBJECT (window), "ret", &ret);
\r
900 gtk_widget_realize (window);
\r
902 gtk_window_set_policy(GTK_WINDOW (window),FALSE,FALSE,TRUE);
\r
904 if (parent != NULL)
\r
905 gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (parent));
\r
907 accel = gtk_accel_group_new ();
\r
908 gtk_window_add_accel_group (GTK_WINDOW (window), accel);
\r
910 vbox = gtk_vbox_new (FALSE, 10);
\r
911 gtk_container_add (GTK_CONTAINER (window), vbox);
\r
912 gtk_widget_show (vbox);
\r
914 w = gtk_label_new (lpText);
\r
915 gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);
\r
916 gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT);
\r
917 gtk_widget_show (w);
\r
919 w = gtk_hseparator_new ();
\r
920 gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);
\r
921 gtk_widget_show (w);
\r
923 hbox = gtk_hbox_new (FALSE, 10);
\r
924 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
\r
925 gtk_widget_show (hbox);
\r
929 w = gtk_button_new_with_label ("Ok");
\r
930 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
931 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
932 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
\r
933 gtk_widget_add_accelerator (w, "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
\r
934 gtk_widget_add_accelerator (w, "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
\r
935 GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
\r
936 gtk_widget_grab_default (w);
\r
937 gtk_widget_show (w);
\r
940 else if (mode == MB_OKCANCEL)
\r
942 w = gtk_button_new_with_label ("Ok");
\r
943 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
944 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
945 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
\r
946 gtk_widget_add_accelerator (w, "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
\r
947 GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
\r
948 gtk_widget_grab_default (w);
\r
949 gtk_widget_show (w);
\r
951 w = gtk_button_new_with_label ("Cancel");
\r
952 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
953 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
954 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
\r
955 gtk_widget_add_accelerator (w, "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
\r
956 gtk_widget_show (w);
\r
959 else if (mode == MB_YESNOCANCEL)
\r
961 w = gtk_button_new_with_label ("Yes");
\r
962 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
963 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
964 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDYES));
\r
965 GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
\r
966 gtk_widget_grab_default (w);
\r
967 gtk_widget_show (w);
\r
969 w = gtk_button_new_with_label ("No");
\r
970 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
971 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
972 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDNO));
\r
973 gtk_widget_show (w);
\r
975 w = gtk_button_new_with_label ("Cancel");
\r
976 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
977 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
978 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
\r
979 gtk_widget_show (w);
\r
982 else /* if (mode == MB_YESNO) */
\r
984 w = gtk_button_new_with_label ("Yes");
\r
985 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
986 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
987 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDYES));
\r
988 GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
\r
989 gtk_widget_grab_default (w);
\r
990 gtk_widget_show (w);
\r
992 w = gtk_button_new_with_label ("No");
\r
993 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
994 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
995 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDNO));
\r
996 gtk_widget_show (w);
\r
1002 w = gtk_button_new_with_label ("Go to URL");
\r
1003 gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
\r
1004 gtk_signal_connect (GTK_OBJECT (w), "clicked",
\r
1005 GTK_SIGNAL_FUNC (dialog_url_callback), NULL);
\r
1006 g_object_set_data (G_OBJECT (w), "URL", (void *)URL);
\r
1007 GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
\r
1008 gtk_widget_grab_default (w);
\r
1009 gtk_widget_show (w);
\r
1013 gtk_widget_show (window);
\r
1014 gtk_grab_add (window);
\r
1017 gtk_main_iteration ();
\r
1019 gtk_grab_remove (window);
\r
1020 gtk_widget_destroy (window);
\r
1025 // =============================================================================
\r
1028 // fenris #3078 WHENHELLISFROZENOVER
\r
1030 //#define FILEDLG_DBG
\r
1032 static void file_sel_callback (GtkWidget *widget, gpointer data)
\r
1034 GtkWidget *parent;
\r
1038 parent = gtk_widget_get_toplevel (widget);
\r
1039 loop = (int*)g_object_get_data (G_OBJECT (parent), "loop");
\r
1040 success = (bool*)g_object_get_data (G_OBJECT (parent), "success");
\r
1042 if ((int)data == IDOK)
\r
1045 #ifdef FILEDLG_DBG
\r
1047 Sys_Printf("file_sel_callback != IDOK\n");
\r
1054 #include <commdlg.h>
\r
1055 static OPENFILENAME ofn; /* common dialog box structure */
\r
1056 static char szDirName[MAX_PATH]; /* directory string */
\r
1057 static char szFile[MAX_PATH]; /* filename string */
\r
1058 static char szFileTitle[MAX_PATH]; /* file title string */
\r
1059 static int i, cbString; /* integer count variables */
\r
1060 static HANDLE hf; /* file handle */
\r
1062 static char szFile[QER_MAX_NAMELEN];
\r
1065 #define FILEDLG_CUSTOM_FILTER_LENGTH 64
\r
1066 // to be used with the advanced file selector
\r
1068 class CFileType : public IFileTypeList
\r
1070 struct filetype_copy_t
\r
1072 void operator=(const filetype_t& other)
\r
1074 m_name = other.name;
\r
1075 m_pattern = other.pattern;
\r
1078 string_t m_pattern;
\r
1085 m_strWin32Filters = NULL;
\r
1086 m_pstrGTKMasks = NULL;
\r
1089 virtual ~CFileType()
\r
1091 delete[] m_pTypes;
\r
1092 DestroyWin32Filters();
\r
1093 DestroyGTKMasks();
\r
1096 void addType(filetype_t type)
\r
1098 filetype_copy_t* newTypes = new filetype_copy_t [m_nTypes+1];
\r
1101 for(int i=0; i<m_nTypes; i++)
\r
1102 newTypes[i] = m_pTypes[i];
\r
1103 delete[] m_pTypes;
\r
1105 m_pTypes = newTypes;
\r
1106 m_pTypes[m_nTypes] = type;
\r
1108 ConstructGTKMasks();
\r
1109 ConstructWin32Filters();
\r
1112 filetype_t GetTypeForWin32Filter(const char *filter) const
\r
1114 for(int i=0; i<m_nTypes; i++)
\r
1115 if(strcmp(m_pTypes[i].m_pattern.c_str(), filter)==0)
\r
1116 return filetype_t(m_pTypes[i].m_name.c_str(), m_pTypes[i].m_pattern.c_str());
\r
1117 return filetype_t();
\r
1120 filetype_t GetTypeForGTKMask(const char *mask) const
\r
1122 for(int i=0; i<m_nTypes; i++)
\r
1123 if(strcmp(m_pstrGTKMasks[i],mask)==0)
\r
1124 return filetype_t(m_pTypes[i].m_name.c_str(), m_pTypes[i].m_pattern.c_str());
\r
1125 return filetype_t();
\r
1128 char *m_strWin32Filters;
\r
1129 char **m_pstrGTKMasks;
\r
1132 filetype_copy_t *m_pTypes;
\r
1134 void DestroyWin32Filters()
\r
1136 delete[] m_strWin32Filters;
\r
1139 void ConstructWin32Filters()
\r
1145 DestroyWin32Filters();
\r
1146 for(i=0; i<m_nTypes; i++)
\r
1147 len = len + strlen(m_pTypes[i].m_name.c_str()) + strlen(m_pTypes[i].m_pattern.c_str())*2 + 5;
\r
1148 m_strWin32Filters = new char[len+1]; // length + null char
\r
1149 for(i=0, w = m_strWin32Filters; i<m_nTypes; i++)
\r
1151 for(r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)
\r
1155 for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
\r
1159 for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
\r
1160 *w = (*r == ',') ? ';' : *r;
\r
1163 m_strWin32Filters[len] = '\0';
\r
1166 void DestroyGTKMasks()
\r
1168 if(m_pstrGTKMasks != NULL)
\r
1169 for(char **p = m_pstrGTKMasks; *p != NULL; p++)
\r
1171 delete[] m_pstrGTKMasks;
\r
1174 void ConstructGTKMasks()
\r
1180 DestroyGTKMasks();
\r
1181 m_pstrGTKMasks = new char*[m_nTypes+1];
\r
1182 for(i=0; i<m_nTypes; i++)
\r
1184 len = strlen(m_pTypes[i].m_name.c_str()) + strlen(m_pTypes[i].m_pattern.c_str()) + 3;
\r
1185 m_pstrGTKMasks[i] = new char[len+1]; // length + null char
\r
1186 w = m_pstrGTKMasks[i];
\r
1187 for(r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)
\r
1191 for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
\r
1196 m_pstrGTKMasks[m_nTypes] = NULL;
\r
1201 const char* file_dialog (void *parent, gboolean open, const char* title, const char* path, const char* pattern)
\r
1204 GtkWidget* file_sel;
\r
1206 char *new_path = NULL;
\r
1211 CFileType typelist;
\r
1212 if(pattern != NULL)
\r
1213 GetFileTypeRegistry()->getTypeList(pattern, &typelist);
\r
1215 #ifdef FILEDLG_DBG
\r
1216 Sys_Printf("file_dialog: open = %d title = %s path = %s\n", open, title, path);
\r
1219 Sys_Printf("Patterns:\n");
\r
1220 char** p = typelist.m_pstrGTKMasks;
\r
1222 Sys_Printf("%s\n", *p++);
\r
1225 Sys_Printf("no patterns\n");
\r
1229 // win32 dialog stores the selected "save as type" extension in the second null-terminated string
\r
1230 char customfilter[FILEDLG_CUSTOM_FILTER_LENGTH];
\r
1232 if (g_PrefsDlg.m_bNativeGUI)
\r
1234 #ifdef FILEDLG_DBG
\r
1235 Sys_Printf("Doing win32 file dialog...");
\r
1237 // do that the native way
\r
1238 /* Place the terminating null character in the szFile. */
\r
1240 customfilter[0] = customfilter[1] = customfilter[2] = '\0';
\r
1242 /* Set the members of the OPENFILENAME structure. */
\r
1243 ofn.lStructSize = sizeof(OPENFILENAME);
\r
1244 ofn.hwndOwner = (HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window);
\r
1247 ofn.nFilterIndex = 0;
\r
1248 ofn.lpstrFilter = typelist.m_strWin32Filters;
\r
1250 else ofn.nFilterIndex = 1;
\r
1251 ofn.lpstrCustomFilter = customfilter;
\r
1252 ofn.nMaxCustFilter = sizeof(customfilter);
\r
1253 ofn.lpstrFile = szFile;
\r
1254 ofn.nMaxFile = sizeof(szFile);
\r
1255 ofn.lpstrFileTitle = NULL; // we don't need to get the name of the file
\r
1258 // szDirName: Radiant uses unix convention for paths internally
\r
1259 // Win32 (of course) and Gtk (who would have thought) expect the '\\' convention
\r
1260 // copy path, replacing dir separators as appropriate
\r
1261 for(r=path, w=szDirName; *r!='\0'; r++)
\r
1262 *w++ = (*r=='/') ? '\\' : *r;
\r
1263 // terminate string
\r
1265 ofn.lpstrInitialDir = szDirName;
\r
1267 else ofn.lpstrInitialDir = NULL;
\r
1268 ofn.lpstrTitle = title;
\r
1269 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
\r
1271 /* Display the Open dialog box. */
\r
1272 // it's open or close depending on 'open' parameter
\r
1275 if (!GetOpenFileName(&ofn))
\r
1276 return NULL; // canceled
\r
1280 if (!GetSaveFileName(&ofn))
\r
1281 return NULL; // canceled
\r
1284 if(pattern != NULL)
\r
1285 type = typelist.GetTypeForWin32Filter(customfilter+1);
\r
1287 #ifdef FILEDLG_DBG
\r
1288 Sys_Printf("Done.\n");
\r
1294 // do that the Gtk way
\r
1295 if (title == NULL)
\r
1296 title = open ? "Open File" : "Save File";
\r
1298 #ifdef FILEDLG_DBG
\r
1299 Sys_Printf("Doing Gtk file dialog:\nBuilding new_path..");
\r
1301 // we expect an actual path below, if the path is NULL we might crash
\r
1302 if (!path || path[0] == '\0')
\r
1306 #elif defined (__linux__) || defined (__APPLE__)
\r
1313 // alloc new path with extra char for dir separator
\r
1314 new_path = new char[strlen(path)+1+1];
\r
1315 // copy path, replacing dir separators as appropriate
\r
1316 for(r=path, w=new_path; *r!='\0'; r++)
\r
1317 *w++ = (*r=='/') ? G_DIR_SEPARATOR : *r;
\r
1318 // add dir separator to end of path if required
\r
1319 if(*(w-1) != G_DIR_SEPARATOR) *w++ = G_DIR_SEPARATOR;
\r
1320 // terminate string
\r
1323 #ifdef FILEDLG_DBG
\r
1324 Sys_Printf("Done.\n");
\r
1325 Sys_Printf("Calling gtk_file_selection_new with title: %s...", title);
\r
1328 file_sel = gtk_file_selection_new (title);
\r
1330 #ifdef FILEDLG_DBG
\r
1331 Sys_Printf("Done.\n");
\r
1332 Sys_Printf("Set the masks...");
\r
1335 #if 0 //!\todo Add masks to GtkFileSelection in gtk-2.0
\r
1339 gtk_file_selection_clear_masks (GTK_FILE_SELECTION (file_sel));
\r
1340 gtk_file_selection_set_masks (GTK_FILE_SELECTION (file_sel), const_cast<const char**>(typelist.m_pstrGTKMasks));
\r
1344 #ifdef FILEDLG_DBG
\r
1345 Sys_Printf("Done.\n");
\r
1348 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), "clicked",
\r
1349 GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDOK));
\r
1350 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->cancel_button), "clicked",
\r
1351 GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDCANCEL));
\r
1352 gtk_signal_connect (GTK_OBJECT (file_sel), "delete_event",
\r
1353 GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
\r
1354 gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));
\r
1356 if (parent != NULL)
\r
1357 gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));
\r
1359 #ifdef FILEDLG_DBG
\r
1360 Sys_Printf("set_data...");
\r
1362 bool success = false;
\r
1363 g_object_set_data (G_OBJECT (file_sel), "loop", &loop);
\r
1364 g_object_set_data (G_OBJECT (file_sel), "success", &success);
\r
1365 #ifdef FILEDLG_DBG
\r
1366 Sys_Printf("Done.\n");
\r
1371 #ifdef FILEDLG_DBG
\r
1372 Sys_Printf("set_data \"overwrite\" ...");
\r
1374 g_object_set_data (G_OBJECT (file_sel), "overwrite", GINT_TO_POINTER (1));
\r
1375 #ifdef FILEDLG_DBG
\r
1376 Sys_Printf("Done.\n");
\r
1380 if (new_path != NULL)
\r
1382 #ifdef FILEDLG_DBG
\r
1383 Sys_Printf("gtk_file_selection_set_filename... %p", file_sel);
\r
1385 gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), new_path);
\r
1386 delete[] new_path;
\r
1387 #ifdef FILEDLG_DBG
\r
1388 Sys_Printf("Done.\n");
\r
1392 gtk_grab_add (file_sel);
\r
1393 #ifdef FILEDLG_DBG
\r
1394 Sys_Printf("gtk_widget_show... %p", file_sel);
\r
1396 gtk_widget_show (file_sel);
\r
1397 #ifdef FILEDLG_DBG
\r
1398 Sys_Printf("Done.\n");
\r
1401 #ifdef FILEDLG_DBG
\r
1402 Sys_Printf("gtk_main_iteration...");
\r
1405 gtk_main_iteration ();
\r
1408 #if 0 //!\todo Add masks to GtkFileSelection in gtk2
\r
1410 type = typelist.GetTypeForGTKMask(GTK_FILE_SELECTION (file_sel)->mask);
\r
1412 strcpy(szFile, gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));
\r
1414 #ifdef FILEDLG_DBG
\r
1415 Sys_Printf("Done.\n");
\r
1418 gtk_grab_remove (file_sel);
\r
1419 gtk_widget_destroy (file_sel);
\r
1424 // don't return an empty filename
\r
1425 if(szFile[0] == '\0') return NULL;
\r
1427 // convert back to unix format
\r
1428 for(w=szFile; *w!='\0'; w++)
\r
1432 #if defined(WIN32)
\r
1433 if (g_PrefsDlg.m_bNativeGUI) // filetype mask not supported in gtk dialog yet
\r
1435 // when saving, force an extension depending on filetype
\r
1436 /* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */
\r
1437 if(!open && pattern != NULL)
\r
1439 // last ext separator
\r
1440 w = strrchr(szFile, '.');
\r
1442 w = (w!=NULL) ? w : szFile+strlen(szFile);
\r
1443 strcpy(w, type.pattern+1);
\r
1448 // prompt to overwrite existing files
\r
1450 if (access (szFile, R_OK) == 0)
\r
1451 if (gtk_MessageBox (parent, "File already exists.\nOverwrite?", "GtkRadiant", MB_YESNO) == IDNO)
\r
1454 #ifdef FILEDLG_DBG
\r
1455 // ... let's use a static filename
\r
1456 Sys_Printf("filename: %p\n", szFile);
\r
1462 char* WINAPI dir_dialog (void *parent, const char* title, const char* path)
\r
1464 GtkWidget* file_sel;
\r
1465 char* filename = (char*)NULL;
\r
1467 bool success = false;
\r
1469 file_sel = gtk_file_selection_new (title);
\r
1470 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), "clicked",
\r
1471 GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDOK));
\r
1472 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->cancel_button), "clicked",
\r
1473 GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDCANCEL));
\r
1474 gtk_signal_connect (GTK_OBJECT (file_sel), "delete_event",
\r
1475 GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
\r
1476 gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));
\r
1478 if (parent != NULL)
\r
1479 gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));
\r
1481 gtk_widget_hide (GTK_FILE_SELECTION (file_sel)->file_list->parent);
\r
1483 g_object_set_data (G_OBJECT (file_sel), "loop", &loop);
\r
1484 g_object_set_data (G_OBJECT (file_sel), "filename", &filename);
\r
1485 g_object_set_data (G_OBJECT (file_sel), "success", &success);
\r
1488 gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), path);
\r
1490 gtk_grab_add (file_sel);
\r
1491 gtk_widget_show (file_sel);
\r
1494 gtk_main_iteration ();
\r
1496 filename = g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));
\r
1498 gtk_grab_remove (file_sel);
\r
1499 gtk_widget_destroy (file_sel);
\r
1504 bool WINAPI color_dialog (void *parent, float *color, const char* title)
\r
1508 int loop = 1, ret = IDCANCEL;
\r
1510 clr[0] = color[0];
\r
1511 clr[1] = color[1];
\r
1512 clr[2] = color[2];
\r
1514 dlg = gtk_color_selection_dialog_new (title);
\r
1515 gtk_color_selection_set_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dlg)->colorsel), clr);
\r
1516 gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
\r
1517 GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
\r
1518 gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
\r
1519 GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
\r
1520 gtk_signal_connect (GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (dlg)->ok_button), "clicked",
\r
1521 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
\r
1522 gtk_signal_connect (GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (dlg)->cancel_button), "clicked",
\r
1523 GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
\r
1524 g_object_set_data (G_OBJECT (dlg), "loop", &loop);
\r
1525 g_object_set_data (G_OBJECT (dlg), "ret", &ret);
\r
1527 if (parent != NULL)
\r
1528 gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (parent));
\r
1530 gtk_widget_show (dlg);
\r
1531 gtk_grab_add (dlg);
\r
1534 gtk_main_iteration ();
\r
1536 GdkColor gdkcolor;
\r
1537 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dlg)->colorsel), &gdkcolor);
\r
1538 clr[0] = gdkcolor.red / 65535.0;
\r
1539 clr[1] = gdkcolor.green / 65535.0;
\r
1540 clr[2] = gdkcolor.blue / 65535.0;
\r
1542 gtk_grab_remove (dlg);
\r
1543 gtk_widget_destroy (dlg);
\r
1547 color[0] = (float)clr[0];
\r
1548 color[1] = (float)clr[1];
\r
1549 color[2] = (float)clr[2];
\r
1557 void OpenURL(const char *url)
\r
1559 // let's put a little comment
\r
1560 Sys_Printf("OpenURL: %s\n", url);
\r
1562 // \todo FIXME: the way we open URLs on *nix should be improved. A script is good (see how I do on RTCW)
\r
1563 char command[2*PATH_MAX];
\r
1564 snprintf( command, sizeof(command), "%s/openurl.sh \"%s\" &", g_strAppPath.GetBuffer(), url );
\r
1565 if (system (command) != 0)
\r
1566 gtk_MessageBox (g_pParentWnd->m_pWidget, "Failed to launch Netscape!");
\r
1569 char command[2*PATH_MAX];
\r
1570 snprintf (command, sizeof(command),
\r
1571 "open \"%s\" &", url, url);
\r
1572 if (system (command) != 0)
\r
1573 gtk_MessageBox (g_pParentWnd->m_pWidget, "Unable to launch browser!");
\r
1576 ShellExecute( (HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window), "open", url, NULL, NULL, SW_SHOW );
\r
1580 void CheckMenuSplitting (GtkWidget *&menu)
\r
1582 GtkWidget *item,*menu2;
\r
1584 GtkRequisition requisition;
\r
1585 gint screen_height;
\r
1587 gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
\r
1588 screen_height = gdk_screen_height ();
\r
1590 if ((screen_height - requisition.height) < 20)
\r
1592 menu2 = gtk_menu_new ();
\r
1594 // move the last 2 items to a submenu (3 because of win32)
\r
1595 for (int i = 0; i < 3; i++)
\r
1597 item = GTK_WIDGET (g_list_last (gtk_container_children (GTK_CONTAINER (menu)))->data);
\r
1598 gtk_widget_ref (item);
\r
1599 gtk_container_remove (GTK_CONTAINER (menu), item);
\r
1600 gtk_menu_append (GTK_MENU (menu2), item);
\r
1601 gtk_widget_unref (item);
\r
1604 item = gtk_menu_item_new_with_label ("--------");
\r
1605 gtk_widget_show (item);
\r
1606 gtk_container_add (GTK_CONTAINER (menu), item);
\r
1607 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu2);
\r