-/*\r
-Copyright (c) 2001, Loki software, inc.\r
-All rights reserved.\r
-\r
-Redistribution and use in source and binary forms, with or without modification, \r
-are permitted provided that the following conditions are met:\r
-\r
-Redistributions of source code must retain the above copyright notice, this list \r
-of conditions and the following disclaimer.\r
-\r
-Redistributions in binary form must reproduce the above copyright notice, this\r
-list of conditions and the following disclaimer in the documentation and/or\r
-other materials provided with the distribution.\r
-\r
-Neither the name of Loki software nor the names of its contributors may be used \r
-to endorse or promote products derived from this software without specific prior \r
-written permission. \r
-\r
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' \r
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \r
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY \r
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES \r
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \r
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS \r
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \r
-*/\r
-\r
-//\r
-// Small functions to help with GTK\r
-//\r
-\r
-#include <gdk/gdkkeysyms.h>\r
-\r
-#if defined (__linux__) || defined (__APPLE__)\r
-#include <unistd.h>\r
-#endif\r
-\r
-#include <gtk/gtk.h>\r
-\r
-\r
-#ifdef _WIN32\r
-#include <gdk/gdkwin32.h>\r
-#define WIN32_LEAN_AND_MEAN\r
-#include <windows.h>\r
-#endif\r
-\r
-\r
-\r
-#ifdef _WIN32\r
-#include <io.h>\r
-#include <direct.h>\r
-#define R_OK 04\r
-#endif\r
-#include "stdafx.h"\r
-\r
-// =============================================================================\r
-// Misc stuff\r
-\r
-// NOTE TTimo window position saving has always been tricky\r
-// it doesn't work the same between win32 and linux .. see below that code is fairly different\r
-// it's also very poorly done, the save calls are a bit randomly disctributed in the OnDestroy\r
-\r
-void save_window_pos (GtkWidget *wnd, window_position_t& pos)\r
-{\r
- if ((wnd == NULL) || (wnd->window == NULL))\r
- return;\r
-\r
- get_window_pos(wnd, &pos.x, &pos.y);\r
-\r
- pos.w = wnd->allocation.width;\r
- pos.h = wnd->allocation.height;\r
-\r
-#ifdef DBG_WINDOWPOS\r
- //Sys_Printf("save_window_pos 'Window %s'\n",buf);\r
-#endif\r
-}\r
-\r
-#ifdef _WIN32\r
-void win32_get_window_pos(GtkWidget *widget, gint *x, gint *y)\r
-{\r
- // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=913\r
- if ( g_PrefsDlg.m_bStartOnPrimMon ) {\r
- RECT rc;\r
- POINT point;\r
- HWND xwnd = (HWND)GDK_WINDOW_HWND (widget->window);\r
- const GdkRectangle primaryMonitorRect = g_pParentWnd->GetPrimaryMonitorRect();\r
-\r
- GetClientRect(xwnd,&rc);\r
- point.x=rc.left;\r
- point.y=rc.top;\r
- ClientToScreen(xwnd,&point);\r
-\r
- *x=point.x;\r
- *y=point.y;\r
-\r
- *x=max(*x,-widget->allocation.width+10);\r
- *x=min(*x,primaryMonitorRect.width-10);\r
- *y=max(*y,-widget->allocation.height+10);\r
- *y=min(*y,primaryMonitorRect.height-10);\r
- } else {\r
- // this is the same as the unix version of get_window_pos\r
- gdk_window_get_root_origin (widget->window, x, y);\r
- }\r
-#ifdef DBG_WINDOWPOS\r
- Sys_Printf("win32_get_window_pos %p %d,%d\n",widget,*x,*y);\r
-#endif \r
-}\r
-#endif\r
-\r
-void load_window_pos (GtkWidget *wnd, window_position_t& pos)\r
-{\r
-#ifdef _WIN32\r
- const GdkRectangle primaryMonitorRect = g_pParentWnd->GetPrimaryMonitorRect();\r
-\r
- if(pos.x < primaryMonitorRect.x\r
- || pos.y < primaryMonitorRect.y\r
- || pos.x > primaryMonitorRect.x + primaryMonitorRect.width\r
- || pos.y > primaryMonitorRect.y + primaryMonitorRect.height)\r
- gtk_window_set_position(GTK_WINDOW(wnd), GTK_WIN_POS_CENTER_ON_PARENT);\r
-#else\r
- // FIXME: not multihead safe\r
- if(pos.x < 0\r
- || pos.y < 0\r
- || pos.x > gdk_screen_width ()\r
- || pos.y > gdk_screen_height ())\r
- gtk_window_set_position(GTK_WINDOW(wnd), GTK_WIN_POS_CENTER_ON_PARENT);\r
-#endif\r
- else\r
- gtk_window_move(GTK_WINDOW(wnd), pos.x, pos.y);\r
-\r
- gtk_window_set_default_size (GTK_WINDOW (wnd), pos.w, pos.h);\r
-#ifdef DBG_WINDOWPOS\r
- Sys_Printf("load_window_pos %p 'Window,%s'\n",wnd,windowData);\r
-#endif\r
-}\r
-\r
-gint widget_delete_hide (GtkWidget *widget)\r
-{\r
- gtk_widget_hide (widget);\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-// Thanks to Mercury, Fingolfin - ETG\r
-int readLongLE(FILE *file, unsigned long *m_bytesRead, int *value)\r
-{\r
- byte buf[4];\r
- int len = fread(buf, 4, 1, file);\r
- *m_bytesRead += 4;\r
- if (len != 1)\r
- return -1;\r
-\r
- *value = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;\r
- return 0;\r
-}\r
-\r
-short readShortLE(FILE *file, unsigned long *m_bytesRead, short unsigned *value)\r
-{\r
- byte buf[2];\r
- int len = fread(buf, 2, 1, file);\r
- *m_bytesRead += 2;\r
- if (len != 1)\r
- return -1;\r
-\r
- *value = buf[0] | buf[1] << 8;\r
- return 0;\r
-}\r
-\r
-unsigned char *load_bitmap_file (const char* filename, guint16 *width, guint16 *height)\r
-{\r
- int bmWidth, bmHeight;\r
- short unsigned bmPlanes, bmBitsPixel;\r
- typedef struct {\r
- unsigned char rgbBlue;\r
- unsigned char rgbGreen;\r
- unsigned char rgbRed;\r
- unsigned char rgbReserved;\r
- } RGBQUAD;\r
- unsigned char m1,m2;\r
- int sizeimage;\r
- short unsigned res1,res2;\r
- int filesize, pixoff;\r
- int bmisize, compression;\r
- int xscale, yscale;\r
- int colors, impcol;\r
- unsigned long m_bytesRead = 0;\r
- unsigned char *imagebits = NULL;\r
- FILE *fp;\r
-\r
- *width = *height = 0;\r
-\r
- fp = fopen(filename,"rb");\r
- if (fp == NULL)\r
- {\r
- return NULL;\r
- }\r
-\r
- size_t rc;\r
- rc = fread(&m1, 1, 1, fp);\r
- m_bytesRead++;\r
- if (rc == -1)\r
- {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- rc = fread(&m2, 1, 1, fp);\r
- m_bytesRead++;\r
- if ((m1!='B') || (m2!='M'))\r
- {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&filesize)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readShortLE(fp,&m_bytesRead,&res1)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readShortLE(fp,&m_bytesRead,&res2)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&pixoff)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&bmisize)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&bmWidth)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&bmHeight)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readShortLE(fp,&m_bytesRead,&bmPlanes)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readShortLE(fp,&m_bytesRead,&bmBitsPixel)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&compression)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&sizeimage)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&xscale)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&yscale)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&colors)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (readLongLE(fp,&m_bytesRead,&impcol)) {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- if (colors == 0)\r
- colors = 1 << bmBitsPixel;\r
-\r
- RGBQUAD *colormap = NULL;\r
- if (bmBitsPixel != 24)\r
- {\r
- colormap = new RGBQUAD[colors];\r
- if (colormap == NULL)\r
- {\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- int i;\r
- for (i = 0; i < colors; i++)\r
- {\r
- unsigned char r ,g, b, dummy;\r
-\r
- rc = fread(&b, 1, 1, fp);\r
- m_bytesRead++;\r
- if (rc!=1)\r
- {\r
- delete [] colormap;\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- rc = fread(&g, 1, 1, fp); \r
- m_bytesRead++;\r
- if (rc!=1)\r
- {\r
- delete [] colormap;\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- rc = fread(&r, 1, 1, fp); \r
- m_bytesRead++;\r
- if (rc != 1)\r
- {\r
- delete [] colormap;\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- rc = fread(&dummy, 1, 1, fp); \r
- m_bytesRead++;\r
- if (rc != 1)\r
- {\r
- delete [] colormap;\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- colormap[i].rgbRed=r;\r
- colormap[i].rgbGreen=g;\r
- colormap[i].rgbBlue=b;\r
- }\r
- }\r
-\r
- if ((long)m_bytesRead > pixoff)\r
- {\r
- delete [] colormap;\r
- fclose(fp);\r
- return NULL;\r
- }\r
-\r
- while ((long)m_bytesRead < pixoff)\r
- {\r
- char dummy;\r
- fread(&dummy,1,1,fp);\r
- m_bytesRead++;\r
- }\r
-\r
- int w = bmWidth;\r
- int h = bmHeight;\r
-\r
- // set the output params\r
- imagebits = (unsigned char *)malloc(w * h * 3);\r
- long row_size = w * 3;\r
-\r
- if (imagebits != NULL) \r
- {\r
- *width = w;\r
- *height = h;\r
- unsigned char *outbuf = imagebits;\r
- long row = 0;\r
- long rowOffset = 0;\r
-\r
- if (compression == 0) // BI_RGB\r
- {\r
- // read rows in reverse order\r
- for (row = bmHeight - 1; row >= 0; row--)\r
- {\r
- // which row are we working on?\r
- rowOffset = (long unsigned)row * row_size; \r
-\r
- if (bmBitsPixel == 24)\r
- {\r
- for (int col=0;col<w;col++)\r
- {\r
- long offset = col * 3;\r
- char pixel[3];\r
-\r
- if (fread((void *)(pixel),1,3,fp) == 3)\r
- {\r
- // we swap red and blue here\r
- *(outbuf + rowOffset + offset + 0) = pixel[2]; // r\r
- *(outbuf + rowOffset + offset + 1) = pixel[1]; // g\r
- *(outbuf + rowOffset + offset + 2) = pixel[0]; // b\r
- }\r
- }\r
- m_bytesRead += row_size;\r
-\r
- // read DWORD padding\r
- while ((m_bytesRead - pixoff) & 3)\r
- {\r
- char dummy;\r
- if (fread(&dummy,1,1,fp) != 1)\r
- {\r
- free(imagebits);\r
- fclose(fp);\r
- return NULL;\r
- }\r
- m_bytesRead++;\r
- }\r
- }\r
- else\r
- {\r
- // pixels are packed as 1 , 4 or 8 bit vals. need to unpack them\r
- int bit_count = 0;\r
- unsigned long mask = (1 << bmBitsPixel) - 1;\r
- unsigned char inbyte = 0;\r
-\r
- for (int col = 0; col < w; col++)\r
- {\r
- int pix = 0;\r
-\r
- // if we need another byte\r
- if (bit_count <= 0)\r
- {\r
- bit_count = 8;\r
- if (fread(&inbyte,1,1,fp) != 1)\r
- {\r
- free(imagebits);\r
- delete [] colormap;\r
- fclose(fp);\r
- return NULL;\r
- }\r
- m_bytesRead++;\r
- }\r
-\r
- // keep track of where we are in the bytes\r
- bit_count -= bmBitsPixel;\r
- pix = ( inbyte >> bit_count) & mask;\r
-\r
- // lookup the color from the colormap - stuff it in our buffer\r
- // swap red and blue\r
- *(outbuf + rowOffset + col * 3 + 2) = colormap[pix].rgbBlue;\r
- *(outbuf + rowOffset + col * 3 + 1) = colormap[pix].rgbGreen;\r
- *(outbuf + rowOffset + col * 3 + 0) = colormap[pix].rgbRed;\r
- }\r
-\r
- // read DWORD padding\r
- while ((m_bytesRead - pixoff) & 3)\r
- {\r
- char dummy;\r
- if (fread(&dummy,1,1,fp)!=1)\r
- {\r
- free(imagebits);\r
- if (colormap)\r
- delete [] colormap;\r
- fclose(fp);\r
- return NULL;\r
- }\r
- m_bytesRead++;\r
- }\r
- }\r
- }\r
- }\r
- else\r
- {\r
- int i, x = 0;\r
- unsigned char c, c1 = 0, *pp;\r
- row = 0;\r
- pp = outbuf + (bmHeight - 1) * bmWidth * 3;\r
- \r
- if (bmBitsPixel == 8)\r
- {\r
- while (row < bmHeight)\r
- {\r
- c = getc(fp);\r
- \r
- if (c)\r
- {\r
- // encoded mode\r
- c1 = getc(fp);\r
- for (i = 0; i < c; x++, i++)\r
- {\r
- *pp = colormap[c1].rgbRed; pp++;\r
- *pp = colormap[c1].rgbGreen; pp++;\r
- *pp = colormap[c1].rgbBlue; pp++;\r
- }\r
- }\r
- else\r
- {\r
- // c==0x00, escape codes\r
- c = getc(fp);\r
- if (c == 0x00) // end of line\r
- {\r
- row++;\r
- x = 0;\r
- pp = outbuf + (bmHeight - row - 1) * bmWidth * 3;\r
- }\r
- else if (c == 0x01)\r
- break; // end of pic\r
- else if (c == 0x02) // delta\r
- {\r
- c = getc(fp);\r
- x += c;\r
- c = getc(fp);\r
- row += c;\r
- pp = outbuf + x*3 + (bmHeight - row - 1) * bmWidth * 3;\r
- }\r
- else // absolute mode\r
- {\r
- for (i = 0; i < c; x++, i++)\r
- {\r
- c1 = getc(fp);\r
- *pp = colormap[c1].rgbRed; pp++;\r
- *pp = colormap[c1].rgbGreen; pp++;\r
- *pp = colormap[c1].rgbBlue; pp++;\r
- }\r
- \r
- if (c & 1)\r
- getc(fp); // odd length run: read an extra pad byte\r
- }\r
- }\r
- }\r
- }\r
- else if (bmBitsPixel == 4)\r
- {\r
- while (row < bmHeight)\r
- {\r
- c = getc(fp);\r
- \r
- if (c)\r
- {\r
- // encoded mode\r
- c1 = getc(fp);\r
- for (i = 0; i < c; x++, i++)\r
- {\r
- *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++;\r
- *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++;\r
- *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++;\r
- }\r
- }\r
- else\r
- {\r
- // c==0x00, escape codes\r
- c = getc(fp);\r
- \r
- if (c == 0x00) // end of line\r
- {\r
- row++;\r
- x = 0;\r
- pp = outbuf + (bmHeight - row - 1) * bmWidth * 3;\r
- }\r
- else if (c == 0x01)\r
- break; // end of pic\r
- else if (c == 0x02) // delta\r
- {\r
- c = getc(fp);\r
- x += c;\r
- c = getc(fp);\r
- row += c;\r
- pp = outbuf + x * 3 + (bmHeight - row - 1) * bmWidth * 3;\r
- }\r
- else // absolute mode\r
- {\r
- for (i = 0; i < c; x++, i++)\r
- {\r
- if ((i&1) == 0)\r
- c1 = getc(fp);\r
- *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++;\r
- *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++;\r
- *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++;\r
- }\r
- \r
- if (((c & 3) == 1) || ((c & 3) == 2))\r
- getc(fp); // odd length run: read an extra pad byte\r
- }\r
- }\r
- }\r
- }\r
- }\r
- if (colormap)\r
- delete [] colormap;\r
- \r
- fclose(fp);\r
- }\r
- return imagebits;\r
-}\r
-\r
-void bmp_to_pixmap (const char* filename, GdkPixmap **pixmap, GdkBitmap **mask)\r
-{\r
- guint16 width, height;\r
- unsigned char *buf;\r
- GdkWindow *window = gdk_get_default_root_window();\r
- GdkColormap *colormap;\r
- GdkGC* gc = gdk_gc_new (window);\r
- int i, j;\r
- bool hasMask = false;\r
-\r
- *pixmap = *mask = NULL;\r
- buf = load_bitmap_file (filename, &width, &height);\r
- if (!buf)\r
- return;\r
-\r
- colormap = gdk_drawable_get_colormap (window);\r
- *pixmap = gdk_pixmap_new (window, width, height, -1);\r
-\r
- typedef struct\r
- {\r
- GdkColor c;\r
- unsigned char *p;\r
- } PAL;\r
-\r
- for (i = 0; i < height; i++)\r
- {\r
- for (j = 0; j < width; j++)\r
- {\r
- unsigned char *p = &buf[(i * width + j) * 3];\r
- PAL pe;\r
-\r
- pe.c.red = (gushort)(p[0] * 0xFF);\r
- pe.c.green = (gushort)(p[1] * 0xFF);\r
- pe.c.blue = (gushort)(p[2] * 0xFF);\r
- gdk_colormap_alloc_color(colormap, &pe.c, FALSE, TRUE);\r
- gdk_gc_set_foreground(gc, &pe.c);\r
- gdk_draw_point(*pixmap, gc, j, i);\r
-\r
- if (p[0] == 0xFF && p[1] == 0x00 && p[2] == 0xFF)\r
- hasMask = true;\r
- }\r
- }\r
-\r
- gdk_gc_unref (gc);\r
- *mask = gdk_pixmap_new (window, width, height, 1);\r
- gc = gdk_gc_new (*mask);\r
- if (hasMask)\r
- {\r
- for (i = 0; i < height; i++)\r
- {\r
- for (j = 0; j < width; j++)\r
- {\r
- GdkColor mask_pattern;\r
-\r
- // pink is transparent\r
- if ((buf[(i*width+j)*3] == 0xff) &&\r
- (buf[(i*width+j)*3+1] == 0x00) &&\r
- (buf[(i*width+j)*3+2] == 0xff))\r
- mask_pattern.pixel = 0;\r
- else\r
- mask_pattern.pixel = 1;\r
-\r
- gdk_gc_set_foreground (gc, &mask_pattern);\r
- // possible Win32 Gtk bug here\r
- //gdk_draw_point (*mask, gc, j, i);\r
- gdk_draw_line (*mask, gc, j, i, j + 1, i);\r
- }\r
- }\r
- }\r
- else\r
- {\r
- GdkColor mask_pattern;\r
- mask_pattern.pixel = 1;\r
- gdk_gc_set_foreground (gc, &mask_pattern);\r
- gdk_draw_rectangle (*mask, gc, 1, 0, 0, width, height);\r
- }\r
- gdk_gc_unref(gc);\r
- free (buf);\r
-}\r
-\r
-void load_pixmap (const char* filename, GtkWidget* widget, GdkPixmap **gdkpixmap, GdkBitmap **mask)\r
-{\r
- CString str;\r
-\r
- str = g_strBitmapsPath;\r
- str += filename;\r
-\r
- bmp_to_pixmap (str.GetBuffer (), gdkpixmap, mask);\r
- if (*gdkpixmap == NULL)\r
- {\r
- printf("gdkpixmap was null\n");\r
- char *dummy[] = { "1 1 1 1", " c None", " " };\r
- printf("calling gdk_pixmap_create_from_xpm_d\n");\r
- *gdkpixmap = gdk_pixmap_create_from_xpm_d (gdk_get_default_root_window(), mask, NULL, dummy);\r
- }\r
-}\r
-\r
-// this is the same as above but used by the plugins\r
-// GdkPixmap **gdkpixmap, GdkBitmap **mask\r
-bool WINAPI load_plugin_bitmap (const char* filename, void **gdkpixmap, void **mask)\r
-{\r
- CString str;\r
-\r
- str = g_strGameToolsPath;\r
- str += g_strPluginsDir;\r
- str += "bitmaps/";\r
- str += filename;\r
- bmp_to_pixmap (str.GetBuffer (), (GdkPixmap **)gdkpixmap, (GdkBitmap **)mask);\r
-\r
- if (*gdkpixmap == NULL)\r
- {\r
- // look in the core plugins\r
- str = g_strAppPath;\r
- str += g_strPluginsDir;\r
- str += "bitmaps/";\r
- str += filename;\r
- bmp_to_pixmap (str.GetBuffer (), (GdkPixmap **)gdkpixmap, (GdkBitmap **)mask);\r
-\r
- if (*gdkpixmap == NULL)\r
- {\r
- \r
- // look in core modules\r
- str = g_strAppPath;\r
- str += g_strModulesDir;\r
- str += "bitmaps/";\r
- str += filename;\r
- bmp_to_pixmap (str.GetBuffer (), (GdkPixmap **)gdkpixmap, (GdkBitmap **)mask);\r
- \r
- if (*gdkpixmap == NULL)\r
- {\r
- char *dummy[] = { "1 1 1 1", " c None", " " };\r
- *gdkpixmap = gdk_pixmap_create_from_xpm_d (gdk_get_default_root_window(), (GdkBitmap **)mask, NULL, dummy);\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
-}\r
-\r
-// Load a xpm file and return a pixmap widget.\r
-GtkWidget* new_pixmap (GtkWidget* widget, char* filename)\r
-{\r
- GdkPixmap *gdkpixmap;\r
- GdkBitmap *mask;\r
- GtkWidget *pixmap;\r
-\r
- load_pixmap (filename, widget, &gdkpixmap, &mask);\r
- pixmap = gtk_pixmap_new (gdkpixmap, mask);\r
-\r
- gdk_drawable_unref (gdkpixmap);\r
- gdk_drawable_unref (mask);\r
-\r
- return pixmap;\r
-} \r
-\r
-// =============================================================================\r
-// Menu stuff\r
-\r
-GtkWidget* menu_separator (GtkWidget *menu)\r
-{\r
- GtkWidget *menu_item = gtk_menu_item_new ();\r
- gtk_menu_append (GTK_MENU (menu), menu_item);\r
- gtk_widget_set_sensitive (menu_item, FALSE);\r
- gtk_widget_show (menu_item);\r
- return menu_item;\r
-}\r
-\r
-GtkWidget* menu_tearoff (GtkWidget *menu)\r
-{\r
- GtkWidget *menu_item = gtk_tearoff_menu_item_new ();\r
- gtk_menu_append (GTK_MENU (menu), menu_item);\r
-// gtk_widget_set_sensitive (menu_item, FALSE); -- controls whether menu is detachable\r
- gtk_widget_show (menu_item);\r
- return menu_item;\r
-}\r
- \r
-GtkWidget* create_sub_menu_with_mnemonic (GtkWidget *bar, gchar *mnemonic)\r
-{\r
- GtkWidget *item, *sub_menu;\r
-\r
- item = gtk_menu_item_new_with_mnemonic (mnemonic);\r
- gtk_widget_show (item);\r
- gtk_container_add (GTK_CONTAINER (bar), item);\r
-\r
- sub_menu = gtk_menu_new ();\r
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), sub_menu);\r
-\r
- return sub_menu;\r
-}\r
-\r
-extern void AddMenuItem (GtkWidget* menu, unsigned int id);\r
-\r
-GtkWidget* create_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id)\r
-{\r
- GtkWidget *item;\r
-\r
- item = gtk_menu_item_new_with_mnemonic (mnemonic);\r
-\r
- gtk_widget_show (item);\r
- gtk_container_add (GTK_CONTAINER (menu), item);\r
- gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));\r
-\r
- AddMenuItem (item, id);\r
- return item;\r
-}\r
-\r
-GtkWidget* create_check_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id, gboolean active)\r
-{\r
- GtkWidget *item;\r
-\r
- item = gtk_check_menu_item_new_with_mnemonic(mnemonic);\r
-\r
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), active);\r
- gtk_widget_show (item);\r
- gtk_container_add (GTK_CONTAINER (menu), item);\r
- gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));\r
-\r
- AddMenuItem (item, id);\r
- return item;\r
-}\r
-\r
-GtkWidget* create_radio_menu_item_with_mnemonic (GtkWidget *menu, GtkWidget *last, gchar *mnemonic, GtkSignalFunc func, int id, gboolean state)\r
-{\r
- GtkWidget *item;\r
- GSList *group = (GSList*)NULL;\r
-\r
- if (last != NULL)\r
- group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (last));\r
- item = gtk_radio_menu_item_new_with_mnemonic (group, mnemonic);\r
- gtk_check_menu_item_set_state (GTK_CHECK_MENU_ITEM (item), state);\r
-\r
- gtk_widget_show (item);\r
- gtk_container_add (GTK_CONTAINER (menu), item);\r
- gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));\r
-\r
- AddMenuItem (item, id);\r
- return item;\r
-}\r
-\r
-GtkWidget* create_menu_in_menu_with_mnemonic (GtkWidget *menu, const gchar *mnemonic)\r
-{\r
- GtkWidget *item, *submenu;\r
-\r
- item = gtk_menu_item_new_with_mnemonic(mnemonic);\r
- gtk_widget_show (item);\r
- gtk_container_add (GTK_CONTAINER (menu), item);\r
-\r
- submenu = gtk_menu_new ();\r
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);\r
-\r
- return submenu;\r
-}\r
-\r
-// =============================================================================\r
-// Message Boxes\r
-\r
-void dialog_button_callback (GtkWidget *widget, gpointer data)\r
-{\r
- GtkWidget *parent;\r
- int *loop, *ret;\r
-\r
- parent = gtk_widget_get_toplevel (widget);\r
- loop = (int*)g_object_get_data (G_OBJECT (parent), "loop");\r
- ret = (int*)g_object_get_data (G_OBJECT (parent), "ret");\r
-\r
- *loop = 0;\r
- *ret = (int)data;\r
-}\r
-\r
-gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data)\r
-{\r
- int *loop;\r
-\r
- gtk_widget_hide (widget);\r
- loop = (int*)g_object_get_data (G_OBJECT (widget), "loop");\r
- *loop = 0;\r
-\r
- return TRUE;\r
-}\r
-\r
-gint dialog_url_callback (GtkWidget *widget, GdkEvent* event, gpointer data)\r
-{\r
- OpenURL((const char *)g_object_get_data (G_OBJECT (widget), "URL"));\r
-\r
- return TRUE;\r
-}\r
-\r
-int WINAPI gtk_MessageBox (void *parent, const char* lpText, const char* lpCaption, guint32 uType, const char* URL)\r
-{\r
- GtkWidget *window, *w, *vbox, *hbox;\r
- GtkAccelGroup *accel;\r
- int mode = (uType & MB_TYPEMASK), ret, loop = 1;\r
-\r
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);\r
- gtk_signal_connect (GTK_OBJECT (window), "delete_event",\r
- GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);\r
- gtk_signal_connect (GTK_OBJECT (window), "destroy",\r
- GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);\r
- gtk_window_set_title (GTK_WINDOW (window), lpCaption);\r
- gtk_container_border_width (GTK_CONTAINER (window), 10);\r
- g_object_set_data (G_OBJECT (window), "loop", &loop);\r
- g_object_set_data (G_OBJECT (window), "ret", &ret);\r
- gtk_widget_realize (window);\r
-\r
- gtk_window_set_policy(GTK_WINDOW (window),FALSE,FALSE,TRUE);\r
-\r
- if (parent != NULL)\r
- gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (parent));\r
-\r
- accel = gtk_accel_group_new ();\r
- gtk_window_add_accel_group (GTK_WINDOW (window), accel);\r
-\r
- vbox = gtk_vbox_new (FALSE, 10);\r
- gtk_container_add (GTK_CONTAINER (window), vbox);\r
- gtk_widget_show (vbox);\r
-\r
- w = gtk_label_new (lpText);\r
- gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);\r
- gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT);\r
- gtk_widget_show (w);\r
-\r
- w = gtk_hseparator_new ();\r
- gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);\r
- gtk_widget_show (w);\r
-\r
- hbox = gtk_hbox_new (FALSE, 10);\r
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);\r
- gtk_widget_show (hbox);\r
- \r
- if (mode == MB_OK)\r
- {\r
- w = gtk_button_new_with_label ("Ok");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));\r
- gtk_widget_add_accelerator (w, "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);\r
- gtk_widget_add_accelerator (w, "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);\r
- GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);\r
- gtk_widget_grab_default (w);\r
- gtk_widget_show (w);\r
- ret = IDOK;\r
- }\r
- else if (mode == MB_OKCANCEL)\r
- {\r
- w = gtk_button_new_with_label ("Ok");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));\r
- gtk_widget_add_accelerator (w, "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);\r
- GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);\r
- gtk_widget_grab_default (w);\r
- gtk_widget_show (w);\r
-\r
- w = gtk_button_new_with_label ("Cancel");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));\r
- gtk_widget_add_accelerator (w, "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);\r
- gtk_widget_show (w);\r
- ret = IDCANCEL;\r
- }\r
- else if (mode == MB_YESNOCANCEL)\r
- {\r
- w = gtk_button_new_with_label ("Yes");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDYES));\r
- GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);\r
- gtk_widget_grab_default (w);\r
- gtk_widget_show (w);\r
- \r
- w = gtk_button_new_with_label ("No");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDNO));\r
- gtk_widget_show (w);\r
- \r
- w = gtk_button_new_with_label ("Cancel");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));\r
- gtk_widget_show (w);\r
- ret = IDCANCEL;\r
- }\r
- else /* if (mode == MB_YESNO) */\r
- {\r
- w = gtk_button_new_with_label ("Yes");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDYES));\r
- GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);\r
- gtk_widget_grab_default (w);\r
- gtk_widget_show (w);\r
- \r
- w = gtk_button_new_with_label ("No");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDNO));\r
- gtk_widget_show (w);\r
- ret = IDNO;\r
- }\r
-\r
- if (URL)\r
- {\r
- w = gtk_button_new_with_label ("Go to URL");\r
- gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);\r
- gtk_signal_connect (GTK_OBJECT (w), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_url_callback), NULL);\r
- g_object_set_data (G_OBJECT (w), "URL", (void *)URL);\r
- GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);\r
- gtk_widget_grab_default (w);\r
- gtk_widget_show (w);\r
- }\r
-\r
-\r
- gtk_widget_show (window);\r
- gtk_grab_add (window);\r
-\r
- while (loop)\r
- gtk_main_iteration ();\r
-\r
- gtk_grab_remove (window);\r
- gtk_widget_destroy (window);\r
-\r
- return ret;\r
-}\r
-\r
-// =============================================================================\r
-// File dialog\r
-\r
-// fenris #3078 WHENHELLISFROZENOVER\r
-\r
-//#define FILEDLG_DBG\r
-\r
-static void file_sel_callback (GtkWidget *widget, gpointer data)\r
-{\r
- GtkWidget *parent;\r
- int *loop;\r
- bool *success;\r
-\r
- parent = gtk_widget_get_toplevel (widget);\r
- loop = (int*)g_object_get_data (G_OBJECT (parent), "loop");\r
- success = (bool*)g_object_get_data (G_OBJECT (parent), "success");\r
- \r
- if ((int)data == IDOK)\r
- *success = true;\r
-\r
-#ifdef FILEDLG_DBG\r
- else\r
- Sys_Printf("file_sel_callback != IDOK\n");\r
-#endif\r
- \r
- *loop = 0;\r
-}\r
-\r
-#ifdef _WIN32\r
-#include <commdlg.h>\r
-static OPENFILENAME ofn; /* common dialog box structure */ \r
-static char szDirName[MAX_PATH]; /* directory string */ \r
-static char szFile[MAX_PATH]; /* filename string */ \r
-static char szFileTitle[MAX_PATH]; /* file title string */ \r
-static int i, cbString; /* integer count variables */ \r
-static HANDLE hf; /* file handle */ \r
-#else\r
-static char szFile[QER_MAX_NAMELEN];\r
-#endif\r
-\r
-#define FILEDLG_CUSTOM_FILTER_LENGTH 64\r
-// to be used with the advanced file selector\r
-\r
-class CFileType : public IFileTypeList\r
-{\r
- struct filetype_copy_t\r
- {\r
- void operator=(const filetype_t& other)\r
- {\r
- m_name = other.name;\r
- m_pattern = other.pattern;\r
- }\r
- string_t m_name;\r
- string_t m_pattern;\r
- };\r
-public:\r
- CFileType()\r
- {\r
- m_nTypes = 0;\r
- m_pTypes = NULL;\r
- m_strWin32Filters = NULL;\r
- m_pstrGTKMasks = NULL;\r
- }\r
-\r
- virtual ~CFileType()\r
- {\r
- delete[] m_pTypes;\r
- DestroyWin32Filters();\r
- DestroyGTKMasks();\r
- }\r
-\r
- void addType(filetype_t type)\r
- {\r
- filetype_copy_t* newTypes = new filetype_copy_t [m_nTypes+1];\r
- if(m_nTypes > 0)\r
- {\r
- for(int i=0; i<m_nTypes; i++)\r
- newTypes[i] = m_pTypes[i];\r
- delete[] m_pTypes;\r
- }\r
- m_pTypes = newTypes;\r
- m_pTypes[m_nTypes] = type;\r
- m_nTypes++;\r
- ConstructGTKMasks();\r
- ConstructWin32Filters();\r
- }\r
- \r
- filetype_t GetTypeForWin32Filter(const char *filter) const\r
- {\r
- for(int i=0; i<m_nTypes; i++)\r
- if(strcmp(m_pTypes[i].m_pattern.c_str(), filter)==0)\r
- return filetype_t(m_pTypes[i].m_name.c_str(), m_pTypes[i].m_pattern.c_str());\r
- return filetype_t();\r
- }\r
-\r
- filetype_t GetTypeForGTKMask(const char *mask) const\r
- {\r
- for(int i=0; i<m_nTypes; i++)\r
- if(strcmp(m_pstrGTKMasks[i],mask)==0)\r
- return filetype_t(m_pTypes[i].m_name.c_str(), m_pTypes[i].m_pattern.c_str());\r
- return filetype_t();\r
- }\r
-\r
- char *m_strWin32Filters;\r
- char **m_pstrGTKMasks;\r
-private:\r
- int m_nTypes;\r
- filetype_copy_t *m_pTypes;\r
-\r
- void DestroyWin32Filters()\r
- {\r
- delete[] m_strWin32Filters;\r
- }\r
-\r
- void ConstructWin32Filters()\r
- {\r
- const char *r;\r
- char *w;\r
- int i;\r
- int len = 0;\r
- DestroyWin32Filters();\r
- for(i=0; i<m_nTypes; i++)\r
- len = len + strlen(m_pTypes[i].m_name.c_str()) + strlen(m_pTypes[i].m_pattern.c_str())*2 + 5;\r
- m_strWin32Filters = new char[len+1]; // length + null char\r
- for(i=0, w = m_strWin32Filters; i<m_nTypes; i++)\r
- {\r
- for(r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)\r
- *w = *r;\r
- *w++ = ' ';\r
- *w++ = '(';\r
- for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)\r
- *w = *r;\r
- *w++ = ')';\r
- *w++ = '\0';\r
- for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)\r
- *w = (*r == ',') ? ';' : *r;\r
- *w++ = '\0';\r
- }\r
- m_strWin32Filters[len] = '\0';\r
- }\r
-\r
- void DestroyGTKMasks()\r
- {\r
- if(m_pstrGTKMasks != NULL)\r
- for(char **p = m_pstrGTKMasks; *p != NULL; p++)\r
- delete[] *p;\r
- delete[] m_pstrGTKMasks;\r
- }\r
- \r
- void ConstructGTKMasks()\r
- {\r
- const char *r;\r
- char *w;\r
- int i;\r
- int len = 0;\r
- DestroyGTKMasks();\r
- m_pstrGTKMasks = new char*[m_nTypes+1];\r
- for(i=0; i<m_nTypes; i++)\r
- {\r
- len = strlen(m_pTypes[i].m_name.c_str()) + strlen(m_pTypes[i].m_pattern.c_str()) + 3;\r
- m_pstrGTKMasks[i] = new char[len+1]; // length + null char\r
- w = m_pstrGTKMasks[i];\r
- for(r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)\r
- *w = *r;\r
- *w++ = ' ';\r
- *w++ = '<';\r
- for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)\r
- *w = *r;\r
- *w++ = '>';\r
- *w++ = '\0';\r
- }\r
- m_pstrGTKMasks[m_nTypes] = NULL;\r
- }\r
-\r
-};\r
-\r
-const char* file_dialog (void *parent, gboolean open, const char* title, const char* path, const char* pattern)\r
-{\r
- // Gtk dialog\r
- GtkWidget* file_sel;\r
- int loop = 1;\r
- char *new_path = NULL;\r
-\r
- const char* r;\r
- char* w;\r
- filetype_t type;\r
- CFileType typelist;\r
- if(pattern != NULL)\r
- GetFileTypeRegistry()->getTypeList(pattern, &typelist);\r
-\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("file_dialog: open = %d title = %s path = %s\n", open, title, path);\r
- if (pattern)\r
- {\r
- Sys_Printf("Patterns:\n");\r
- char** p = typelist.m_pstrGTKMasks;\r
- while(*p!=NULL)\r
- Sys_Printf("%s\n", *p++);\r
- }\r
- else\r
- Sys_Printf("no patterns\n");\r
-#endif\r
-\r
-#ifdef _WIN32\r
- // win32 dialog stores the selected "save as type" extension in the second null-terminated string\r
- char customfilter[FILEDLG_CUSTOM_FILTER_LENGTH];\r
-\r
- if (g_PrefsDlg.m_bNativeGUI)\r
- {\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Doing win32 file dialog...");\r
-#endif\r
- // do that the native way\r
- /* Place the terminating null character in the szFile. */ \r
- szFile[0] = '\0';\r
- customfilter[0] = customfilter[1] = customfilter[2] = '\0';\r
- \r
- /* Set the members of the OPENFILENAME structure. */ \r
- ofn.lStructSize = sizeof(OPENFILENAME); \r
- ofn.hwndOwner = (HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window);\r
- if (pattern)\r
- {\r
- ofn.nFilterIndex = 0;\r
- ofn.lpstrFilter = typelist.m_strWin32Filters;\r
- }\r
- else ofn.nFilterIndex = 1;\r
- ofn.lpstrCustomFilter = customfilter;\r
- ofn.nMaxCustFilter = sizeof(customfilter);\r
- ofn.lpstrFile = szFile;\r
- ofn.nMaxFile = sizeof(szFile); \r
- ofn.lpstrFileTitle = NULL; // we don't need to get the name of the file\r
- if(path)\r
- {\r
- // szDirName: Radiant uses unix convention for paths internally\r
- // Win32 (of course) and Gtk (who would have thought) expect the '\\' convention\r
- // copy path, replacing dir separators as appropriate\r
- for(r=path, w=szDirName; *r!='\0'; r++)\r
- *w++ = (*r=='/') ? '\\' : *r;\r
- // terminate string\r
- *w = '\0';\r
- ofn.lpstrInitialDir = szDirName;\r
- }\r
- else ofn.lpstrInitialDir = NULL;\r
- ofn.lpstrTitle = title;\r
- ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; \r
-\r
- /* Display the Open dialog box. */\r
- // it's open or close depending on 'open' parameter\r
- if (open)\r
- {\r
- if (!GetOpenFileName(&ofn))\r
- return NULL; // canceled\r
- }\r
- else\r
- {\r
- if (!GetSaveFileName(&ofn))\r
- return NULL; // canceled\r
- }\r
-\r
- if(pattern != NULL)\r
- type = typelist.GetTypeForWin32Filter(customfilter+1);\r
- \r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n");\r
-#endif\r
- }\r
- else\r
- {\r
-#endif\r
- // do that the Gtk way\r
- if (title == NULL)\r
- title = open ? "Open File" : "Save File";\r
- \r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Doing Gtk file dialog:\nBuilding new_path..");\r
-#endif\r
- // we expect an actual path below, if the path is NULL we might crash\r
- if (!path || path[0] == '\0')\r
- {\r
-#ifdef _WIN32\r
- path = "C:\\";\r
-#elif defined (__linux__) || defined (__APPLE__)\r
- path = "/";\r
-#else\r
- path = "/";\r
-#endif\r
- }\r
-\r
- // alloc new path with extra char for dir separator\r
- new_path = new char[strlen(path)+1+1];\r
- // copy path, replacing dir separators as appropriate\r
- for(r=path, w=new_path; *r!='\0'; r++)\r
- *w++ = (*r=='/') ? G_DIR_SEPARATOR : *r;\r
- // add dir separator to end of path if required\r
- if(*(w-1) != G_DIR_SEPARATOR) *w++ = G_DIR_SEPARATOR;\r
- // terminate string\r
- *w = '\0';\r
-\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n");\r
- Sys_Printf("Calling gtk_file_selection_new with title: %s...", title);\r
-#endif\r
-\r
- file_sel = gtk_file_selection_new (title);\r
-\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n");\r
- Sys_Printf("Set the masks...");\r
-#endif\r
-\r
-#if 0 //!\todo Add masks to GtkFileSelection in gtk-2.0\r
- // set the masks\r
- if (pattern)\r
- {\r
- gtk_file_selection_clear_masks (GTK_FILE_SELECTION (file_sel));\r
- gtk_file_selection_set_masks (GTK_FILE_SELECTION (file_sel), const_cast<const char**>(typelist.m_pstrGTKMasks));\r
- }\r
-#endif\r
-\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n");\r
-#endif\r
-\r
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), "clicked",\r
- GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDOK));\r
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->cancel_button), "clicked",\r
- GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDCANCEL));\r
- gtk_signal_connect (GTK_OBJECT (file_sel), "delete_event",\r
- GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);\r
- gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));\r
- \r
- if (parent != NULL)\r
- gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));\r
- \r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("set_data...");\r
-#endif\r
- bool success = false;\r
- g_object_set_data (G_OBJECT (file_sel), "loop", &loop);\r
- g_object_set_data (G_OBJECT (file_sel), "success", &success);\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n");\r
-#endif\r
- \r
- if (!open)\r
- {\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("set_data \"overwrite\" ...");\r
-#endif\r
- g_object_set_data (G_OBJECT (file_sel), "overwrite", GINT_TO_POINTER (1));\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n");\r
-#endif\r
- }\r
- \r
- if (new_path != NULL)\r
- {\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("gtk_file_selection_set_filename... %p", file_sel); \r
-#endif\r
- gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), new_path);\r
- delete[] new_path;\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n");\r
-#endif\r
- }\r
-\r
- gtk_grab_add (file_sel);\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("gtk_widget_show... %p", file_sel); \r
-#endif\r
- gtk_widget_show (file_sel);\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n"); \r
-#endif\r
-\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("gtk_main_iteration..."); \r
-#endif\r
- while (loop)\r
- gtk_main_iteration ();\r
- if(success)\r
- {\r
-#if 0 //!\todo Add masks to GtkFileSelection in gtk2\r
- if(pattern!=NULL)\r
- type = typelist.GetTypeForGTKMask(GTK_FILE_SELECTION (file_sel)->mask);\r
-#endif\r
- strcpy(szFile, gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));\r
- }\r
-#ifdef FILEDLG_DBG\r
- Sys_Printf("Done.\n");\r
-#endif\r
- \r
- gtk_grab_remove (file_sel);\r
- gtk_widget_destroy (file_sel);\r
-#ifdef _WIN32\r
- }\r
-#endif\r
-\r
- // don't return an empty filename\r
- if(szFile[0] == '\0') return NULL;\r
-\r
- // convert back to unix format\r
- for(w=szFile; *w!='\0'; w++)\r
- if(*w=='\\')\r
- *w = '/';\r
-\r
-#if defined(WIN32)\r
- if (g_PrefsDlg.m_bNativeGUI) // filetype mask not supported in gtk dialog yet\r
- {\r
- // when saving, force an extension depending on filetype\r
- /* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */\r
- if(!open && pattern != NULL)\r
- {\r
- // last ext separator\r
- w = strrchr(szFile, '.');\r
- // no extension\r
- w = (w!=NULL) ? w : szFile+strlen(szFile);\r
- strcpy(w, type.pattern+1);\r
- }\r
- }\r
-#endif\r
-\r
- // prompt to overwrite existing files\r
- if (!open)\r
- if (access (szFile, R_OK) == 0)\r
- if (gtk_MessageBox (parent, "File already exists.\nOverwrite?", "GtkRadiant", MB_YESNO) == IDNO)\r
- return NULL;\r
-\r
-#ifdef FILEDLG_DBG\r
- // ... let's use a static filename\r
- Sys_Printf("filename: %p\n", szFile);\r
-#endif\r
-\r
- return szFile;\r
-}\r
-\r
-char* WINAPI dir_dialog (void *parent, const char* title, const char* path)\r
-{\r
- GtkWidget* file_sel;\r
- char* filename = (char*)NULL;\r
- int loop = 1;\r
- bool success = false;\r
-\r
- file_sel = gtk_file_selection_new (title);\r
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), "clicked",\r
- GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDOK));\r
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->cancel_button), "clicked",\r
- GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDCANCEL));\r
- gtk_signal_connect (GTK_OBJECT (file_sel), "delete_event",\r
- GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);\r
- gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));\r
-\r
- if (parent != NULL)\r
- gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));\r
-\r
- gtk_widget_hide (GTK_FILE_SELECTION (file_sel)->file_list->parent);\r
-\r
- g_object_set_data (G_OBJECT (file_sel), "loop", &loop);\r
- g_object_set_data (G_OBJECT (file_sel), "filename", &filename);\r
- g_object_set_data (G_OBJECT (file_sel), "success", &success);\r
-\r
- if (path != NULL)\r
- gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), path);\r
-\r
- gtk_grab_add (file_sel);\r
- gtk_widget_show (file_sel);\r
-\r
- while (loop)\r
- gtk_main_iteration ();\r
-\r
- filename = g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));\r
-\r
- gtk_grab_remove (file_sel);\r
- gtk_widget_destroy (file_sel);\r
-\r
- return filename;\r
-}\r
-\r
-bool WINAPI color_dialog (void *parent, float *color, const char* title)\r
-{\r
- GtkWidget* dlg;\r
- double clr[3];\r
- int loop = 1, ret = IDCANCEL;\r
-\r
- clr[0] = color[0];\r
- clr[1] = color[1];\r
- clr[2] = color[2];\r
-\r
- dlg = gtk_color_selection_dialog_new (title);\r
- gtk_color_selection_set_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dlg)->colorsel), clr);\r
- gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",\r
- GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);\r
- gtk_signal_connect (GTK_OBJECT (dlg), "destroy",\r
- GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);\r
- gtk_signal_connect (GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (dlg)->ok_button), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));\r
- gtk_signal_connect (GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (dlg)->cancel_button), "clicked",\r
- GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));\r
- g_object_set_data (G_OBJECT (dlg), "loop", &loop);\r
- g_object_set_data (G_OBJECT (dlg), "ret", &ret);\r
-\r
- if (parent != NULL)\r
- gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (parent));\r
-\r
- gtk_widget_show (dlg);\r
- gtk_grab_add (dlg);\r
-\r
- while (loop)\r
- gtk_main_iteration ();\r
-\r
- GdkColor gdkcolor;\r
- gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dlg)->colorsel), &gdkcolor);\r
- clr[0] = gdkcolor.red / 65535.0;\r
- clr[1] = gdkcolor.green / 65535.0;\r
- clr[2] = gdkcolor.blue / 65535.0;\r
-\r
- gtk_grab_remove (dlg);\r
- gtk_widget_destroy (dlg);\r
-\r
- if (ret == IDOK)\r
- {\r
- color[0] = (float)clr[0];\r
- color[1] = (float)clr[1];\r
- color[2] = (float)clr[2];\r
-\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-void OpenURL(const char *url)\r
-{\r
- // let's put a little comment\r
- Sys_Printf("OpenURL: %s\n", url);\r
-#ifdef __linux__\r
- // \todo FIXME: the way we open URLs on *nix should be improved. A script is good (see how I do on RTCW)\r
- char command[2*PATH_MAX];\r
- snprintf( command, sizeof(command), "%s/openurl.sh \"%s\" &", g_strAppPath.GetBuffer(), url );\r
- if (system (command) != 0)\r
- gtk_MessageBox (g_pParentWnd->m_pWidget, "Failed to launch Netscape!");\r
-#endif\r
-#ifdef __APPLE__\r
- char command[2*PATH_MAX];\r
- snprintf (command, sizeof(command),\r
- "open \"%s\" &", url, url);\r
- if (system (command) != 0)\r
- gtk_MessageBox (g_pParentWnd->m_pWidget, "Unable to launch browser!");\r
-#endif\r
-#ifdef _WIN32\r
- ShellExecute( (HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window), "open", url, NULL, NULL, SW_SHOW );\r
-#endif\r
-}\r
-\r
-void CheckMenuSplitting (GtkWidget *&menu)\r
-{\r
- GtkWidget *item,*menu2;\r
-\r
- GtkRequisition requisition;\r
- gint screen_height;\r
-\r
- gtk_widget_size_request (GTK_WIDGET (menu), &requisition);\r
- screen_height = gdk_screen_height ();\r
-\r
- if ((screen_height - requisition.height) < 20)\r
- {\r
- menu2 = gtk_menu_new ();\r
-\r
- // move the last 2 items to a submenu (3 because of win32)\r
- for (int i = 0; i < 3; i++)\r
- {\r
- item = GTK_WIDGET (g_list_last (gtk_container_children (GTK_CONTAINER (menu)))->data);\r
- gtk_widget_ref (item);\r
- gtk_container_remove (GTK_CONTAINER (menu), item);\r
- gtk_menu_append (GTK_MENU (menu2), item);\r
- gtk_widget_unref (item);\r
- }\r
-\r
- item = gtk_menu_item_new_with_label ("--------");\r
- gtk_widget_show (item);\r
- gtk_container_add (GTK_CONTAINER (menu), item);\r
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu2);\r
- menu = menu2;\r
- }\r
-}\r