23dd0b0299
* BUG: Do not search text inside form anymore. [INTERPRETER] * BUG: The startup class is not global anymore, so that it does not conflict with anythign having the same name in components. The interpreter API that was returning the startup class has been updated to reflect that change. * BUG: File.Name("/a/b/") now returns a void string instead of returning "b", to be coherent with File.Dir(). [GB.DESKTOP] * NEW: Use the new API returning the startup class. [GB.FORM] * BUG: Setting DirView.Root with a path ending with a slash does not crash anymore. [GB.GTK] * NEW: Use the new API returning the startup class. [GB.QT4] * NEW: Use the new API returning the startup class. [GB.SIGNAL] * NEW: Use the new API returning the startup class. git-svn-id: svn://localhost/gambas/trunk@3267 867c0c6c-44f3-4631-809d-bfa615b0a4ec
508 lines
11 KiB
C++
508 lines
11 KiB
C++
/***************************************************************************
|
|
|
|
main.cpp
|
|
|
|
(c) 2004-2006 - Daniel Campos Fernández <dcamposf@gmail.com>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
***************************************************************************/
|
|
|
|
#define __MAIN_C
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "gmemory.h"
|
|
#include "main.h"
|
|
#include "gb.image.h"
|
|
#include "gb.gtk.h"
|
|
#include "watcher.h"
|
|
|
|
#include "x11.h"
|
|
#include "CScreen.h"
|
|
#include "CDraw.h"
|
|
#include "CConst.h"
|
|
#include "CColor.h"
|
|
#include "CFont.h"
|
|
#include "CKey.h"
|
|
#include "CPicture.h"
|
|
#include "CImage.h"
|
|
#include "CClipboard.h"
|
|
#include "CMouse.h"
|
|
#include "CMessage.h"
|
|
#include "CDialog.h"
|
|
#include "CWatcher.h"
|
|
#include "CWidget.h"
|
|
#include "CProgress.h"
|
|
#include "CDrawingArea.h"
|
|
#include "CContainer.h"
|
|
#include "CFrame.h"
|
|
#include "CMenu.h"
|
|
#include "CWindow.h"
|
|
#include "CLabel.h"
|
|
#include "CButton.h"
|
|
#include "CPictureBox.h"
|
|
#include "CTextBox.h"
|
|
#include "CTextArea.h"
|
|
#include "CListBox.h"
|
|
#include "CTreeView.h"
|
|
#include "CSlider.h"
|
|
#include "CTabStrip.h"
|
|
#include "CTrayIcon.h"
|
|
#include "CScrollView.h"
|
|
#include "CSpinBox.h"
|
|
#include "CSplitter.h"
|
|
#include "CStock.h"
|
|
#include "CIconView.h"
|
|
#include "CGridView.h"
|
|
#include "CSeparator.h"
|
|
#include "cprinter.h"
|
|
#include "csvgimage.h"
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <string.h>
|
|
|
|
GB_CLASS CLASS_Picture;
|
|
GB_CLASS CLASS_Image;
|
|
GB_CLASS CLASS_DrawingArea;
|
|
GB_CLASS CLASS_Menu;
|
|
GB_CLASS CLASS_Window;
|
|
GB_CLASS CLASS_Printer;
|
|
GB_CLASS CLASS_SvgImage;
|
|
|
|
static void my_lang(char *lang,int rtl1);
|
|
static void my_error(int code,char *error,char *where);
|
|
static void my_quit (void);
|
|
static void my_main(int *argc, char **argv);
|
|
static void my_timer(GB_TIMER *timer,bool on);
|
|
static void my_wait(int duration);
|
|
static void my_post(void);
|
|
static int my_loop();
|
|
static void my_watch(int fd, int type, void *callback, intptr_t param);
|
|
static bool post_Check=false;
|
|
|
|
static bool _application_keypress = false;
|
|
static GB_FUNCTION _application_keypress_func;
|
|
|
|
int MAIN_scale = 0;
|
|
|
|
extern "C"
|
|
{
|
|
GB_INTERFACE GB EXPORT;
|
|
IMAGE_INTERFACE IMAGE EXPORT;
|
|
|
|
GB_DESC *GB_CLASSES[] EXPORT =
|
|
{
|
|
CDesktopDesc,
|
|
CApplicationTooltipDesc,
|
|
CApplicationDesc,
|
|
CSelectDesc,
|
|
CAlignDesc,
|
|
CArrangeDesc,
|
|
CBorderDesc,
|
|
CScrollDesc,
|
|
CLineDesc,
|
|
CFillDesc,
|
|
CColorDesc,
|
|
CFontsDesc,
|
|
CFontDesc,
|
|
CKeyDesc,
|
|
CImageDesc,
|
|
CPictureDesc,
|
|
CClipboardDesc,
|
|
CDragDesc,
|
|
CCursorDesc,
|
|
CMouseDesc,
|
|
CMessageDesc,
|
|
CDialogDesc,
|
|
CWatcherDesc,
|
|
CWidgetDesc,
|
|
CChildrenDesc,
|
|
CContainerDesc,
|
|
CDrawingAreaDesc,
|
|
CFrameDesc,
|
|
CHSplitDesc,
|
|
CVSplitDesc,
|
|
CUserControlDesc,
|
|
CUserContainerDesc,
|
|
CPanelDesc,
|
|
CHBoxDesc,
|
|
CVBoxDesc,
|
|
CHPanelDesc,
|
|
CVPanelDesc,
|
|
CMenuDesc,
|
|
CMenuChildrenDesc,
|
|
CTrayIconDesc,
|
|
CTrayIconsDesc,
|
|
CWindowMenusDesc,
|
|
CWindowControlsDesc,
|
|
CWindowTypeDesc,
|
|
CWindowDesc,
|
|
CWindowsDesc,
|
|
CFormDesc,
|
|
CProgressDesc,
|
|
CLabelDesc,
|
|
CTextLabelDesc,
|
|
CSliderDesc,
|
|
CScrollBarDesc,
|
|
CButtonDesc,
|
|
CToggleButtonDesc,
|
|
CCheckBoxDesc,
|
|
CRadioButtonDesc,
|
|
CToolButtonDesc,
|
|
CPictureBoxDesc,
|
|
CMovieBoxDesc,
|
|
CListBoxDesc,
|
|
CListBoxItemDesc,
|
|
CTextBoxSelectionDesc,
|
|
CTextBoxDesc,
|
|
CTextAreaDesc,
|
|
CTextAreaSelectionDesc,
|
|
CComboBoxDesc,
|
|
CComboBoxItemDesc,
|
|
CListViewItemDesc,
|
|
CListViewDesc,
|
|
CTreeViewItemDesc,
|
|
CTreeViewDesc,
|
|
CIconViewItemDesc,
|
|
CIconViewDesc,
|
|
CColumnViewItemDesc,
|
|
CColumnViewColumnDesc,
|
|
CColumnViewColumnsDesc,
|
|
CColumnViewDesc,
|
|
CTabStripDesc,
|
|
CTabDesc,
|
|
CTabChildrenDesc,
|
|
CPluginDesc,
|
|
CScrollViewDesc,
|
|
CSpinBoxDesc,
|
|
CSeparatorDesc,
|
|
CGridViewItemDesc,
|
|
CGridViewDataDesc,
|
|
CGridViewColumnDesc,
|
|
CGridViewRowDesc,
|
|
CGridViewColumnsDesc,
|
|
CGridViewRowsDesc,
|
|
CGridViewDesc,
|
|
CStockDesc,
|
|
PrinterDesc,
|
|
SvgImageDesc,
|
|
NULL
|
|
};
|
|
|
|
void *GB_GTK_1[] EXPORT =
|
|
{
|
|
(void *)GTK_INTERFACE_VERSION,
|
|
(void *)my_main,
|
|
(void *)GTK_GetPicture,
|
|
(void *)GTK_GetImage,
|
|
(void *)CGRIDVIEW_footer,
|
|
(void *)CGRIDVIEW_column_footer_text,
|
|
(void *)CGRIDVIEW_columns_get,
|
|
(void *)DRAW_get_drawable,
|
|
(void *)DRAW_get_style,
|
|
(void *)DRAW_get_state,
|
|
(void *)DRAW_get_shadow,
|
|
(void *)DRAW_set_state,
|
|
(void *)DRAW_set_shadow,
|
|
NULL
|
|
};
|
|
|
|
const char *GB_INCLUDE EXPORT = "gb.draw";
|
|
|
|
int EXPORT GB_INIT(void)
|
|
{
|
|
GB.Hook(GB_HOOK_QUIT, (void *)my_quit);
|
|
GB.Hook(GB_HOOK_MAIN, (void *)my_main);
|
|
GB.Hook(GB_HOOK_WAIT, (void *)my_wait);
|
|
GB.Hook(GB_HOOK_LOOP, (void *)my_loop);
|
|
GB.Hook(GB_HOOK_TIMER,(void *)my_timer);
|
|
GB.Hook(GB_HOOK_WATCH,(void *)my_watch);
|
|
GB.Hook(GB_HOOK_POST,(void*)my_post);
|
|
GB.Hook(GB_HOOK_ERROR,(void*)my_error);
|
|
GB.Hook(GB_HOOK_LANG,(void*)my_lang);
|
|
|
|
// Thanks again to GTK+ 2.18 :-(
|
|
#if GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 18
|
|
//putenv((char *)"GDK_NATIVE_WINDOWS=1");
|
|
#endif
|
|
|
|
GB.LoadComponent("gb.draw");
|
|
GB.GetInterface("gb.image", IMAGE_INTERFACE_VERSION, &IMAGE);
|
|
IMAGE.SetDefaultFormat(GB_IMAGE_RGBA);
|
|
DRAW_init();
|
|
|
|
CWatcher::init();
|
|
|
|
//CLASS_Control = GB.FindClass("Control");
|
|
//CLASS_Container = GB.FindClass("Container");
|
|
//CLASS_UserControl = GB.FindClass("UserControl");
|
|
//CLASS_UserContainer = GB.FindClass("UserContainer");
|
|
CLASS_Window = GB.FindClass("Window");
|
|
CLASS_Menu = GB.FindClass("Menu");
|
|
CLASS_Picture = GB.FindClass("Picture");
|
|
//CLASS_Drawing = GB.FindClass("Drawing");
|
|
CLASS_DrawingArea = GB.FindClass("DrawingArea");
|
|
CLASS_Printer = GB.FindClass("Printer");
|
|
CLASS_Image = GB.FindClass("Image");
|
|
CLASS_SvgImage = GB.FindClass("SvgImage");
|
|
|
|
return -1;
|
|
}
|
|
|
|
void EXPORT GB_EXIT()
|
|
{
|
|
CWatcher::exit();
|
|
}
|
|
|
|
int EXPORT GB_INFO(const char *key, void **value)
|
|
{
|
|
if (!strcasecmp(key, "DISPLAY"))
|
|
{
|
|
#ifdef GDK_WINDOWING_X11
|
|
#ifndef GAMBAS_DIRECTFB
|
|
*value = (void *)gdk_x11_display_get_xdisplay(gdk_display_get_default());
|
|
#else
|
|
// For DirectFB
|
|
*value=0;
|
|
stub("DIRECTFB/EXPORT GB_INFO");
|
|
#endif
|
|
#else
|
|
// For Win32
|
|
*value=0;
|
|
stub("no-X11/EXPORT GB_INFO");
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
else if (!strcasecmp(key, "ROOT_WINDOW"))
|
|
{
|
|
#ifdef GDK_WINDOWING_X11
|
|
#ifndef GAMBAS_DIRECTFB
|
|
*value = (void *)gdk_x11_get_default_root_xwindow();
|
|
#else
|
|
// For DirectFB
|
|
*value=0;
|
|
stub("DIRECTFB/EXPORT GB_INFO");
|
|
#endif
|
|
#else
|
|
// For Win32
|
|
*value=0;
|
|
stub("no-X11/EXPORT GB_INFO");
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void my_quit (void)
|
|
{
|
|
CWINDOW *win=WINDOW_get_main();
|
|
|
|
gApplication::suspendEvents(false);
|
|
if (win)
|
|
{
|
|
while (gtk_events_pending ()) gtk_main_iteration();
|
|
if (win->ob.widget) ((gMainWindow*)win->ob.widget)->destroy();
|
|
while (gtk_events_pending ()) gtk_main_iteration();
|
|
}
|
|
|
|
}
|
|
|
|
static bool global_key_event_handler(int type)
|
|
{
|
|
GB.Call(&_application_keypress_func, 0, FALSE);
|
|
return GB.Stopped();
|
|
}
|
|
|
|
static void my_main(int *argc, char **argv)
|
|
{
|
|
static bool init = false;
|
|
|
|
if (init)
|
|
return;
|
|
|
|
gApplication::init(argc, &argv);
|
|
gApplication::setDefaultTitle(GB.Application.Title());
|
|
gDesktop::init();
|
|
MAIN_scale = gDesktop::scale();
|
|
#ifdef GDK_WINDOWING_X11
|
|
X11_init(gdk_x11_display_get_xdisplay(gdk_display_get_default()), gdk_x11_get_default_root_xwindow());
|
|
#endif
|
|
|
|
if (GB.GetFunction(&_application_keypress_func, (void *)GB.Application.StartupClass(), "Application_KeyPress", "", "") == 0)
|
|
{
|
|
_application_keypress = true;
|
|
gApplication::onKeyEvent = global_key_event_handler;
|
|
}
|
|
|
|
init = true;
|
|
}
|
|
|
|
/*static void raise_timer(GB_TIMER *timer)
|
|
{
|
|
GB.RaiseTimer(timer);
|
|
GB.Unref(POINTER(&timer));
|
|
}*/
|
|
|
|
typedef
|
|
struct {
|
|
GTimer *timer;
|
|
int timeout;
|
|
}
|
|
MyTimerTag;
|
|
|
|
gboolean my_timer_function(GB_TIMER *timer)
|
|
{
|
|
if (timer->id)
|
|
{
|
|
GB.RaiseTimer(timer);
|
|
|
|
if (timer->id)
|
|
{
|
|
MyTimerTag *tag = (MyTimerTag *)timer->tag;
|
|
GTimer *t = tag->timer;
|
|
int elapsed = (int)(g_timer_elapsed(t, NULL) * 1000) - tag->timeout;
|
|
int next = timer->delay - elapsed;
|
|
if (next < 10)
|
|
next = 10;
|
|
tag->timeout = next;
|
|
g_timer_start(t);
|
|
timer->id = (intptr_t)g_timeout_add(next, (GSourceFunc)my_timer_function,(gpointer)timer);
|
|
//fprintf(stderr, "elapsed = %d delay = %d next = %d\n", elapsed, timer->delay, next);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static void my_timer(GB_TIMER *timer,bool on)
|
|
{
|
|
if (timer->id) {
|
|
MyTimerTag *tag = (MyTimerTag *)timer->tag;
|
|
g_source_remove(timer->id);
|
|
g_timer_destroy(tag->timer);
|
|
g_free(tag);
|
|
timer->id = 0;
|
|
timer->tag = 0;
|
|
}
|
|
|
|
if (on)
|
|
{
|
|
MyTimerTag *tag = g_new(MyTimerTag, 1);
|
|
tag->timer = g_timer_new();
|
|
tag->timeout = timer->delay;
|
|
timer->tag = (intptr_t)tag;
|
|
timer->id = (intptr_t)g_timeout_add(timer->delay,(GSourceFunc)my_timer_function,(gpointer)timer);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void my_post(void)
|
|
{
|
|
post_Check=true;
|
|
}
|
|
|
|
static bool must_quit(void)
|
|
{
|
|
//fprintf(stderr, "must_quit: %p %d\n", WINDOW_get_main(), CWatcher::count());
|
|
return !WINDOW_get_main() && CWatcher::count() == 0; // && in_event_loop;
|
|
}
|
|
|
|
static int my_loop()
|
|
{
|
|
gControl::cleanRemovedControls();
|
|
|
|
while (!must_quit())
|
|
do_iteration(false);
|
|
|
|
while (gtk_events_pending ()) gtk_main_iteration();
|
|
|
|
CWatcher::Clear();
|
|
gApplication::exit();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void my_wait(int duration)
|
|
{
|
|
do_iteration(true, true);
|
|
}
|
|
|
|
static void my_watch(int fd, int type, void *callback, intptr_t param)
|
|
{
|
|
CWatcher::Add(fd,type,callback,param);
|
|
}
|
|
|
|
static void my_error(int code,char *error,char *where)
|
|
{
|
|
char *showstr;
|
|
char scode[10];
|
|
|
|
sprintf(scode,"%d",code);
|
|
|
|
showstr=g_strconcat("<b>This application has raised an unexpected<br>error and must abort.</b><p>[", scode, "] ", error, ".\n", where, (void *)NULL);
|
|
|
|
gMessage::setTitle(GB.Application.Title());
|
|
gMessage::showError(showstr,NULL,NULL,NULL);
|
|
|
|
g_free(showstr);
|
|
}
|
|
|
|
static void my_lang(char *lang,int rtl)
|
|
{
|
|
int bucle, ct;
|
|
gControl *iter;
|
|
|
|
if (rtl==1)
|
|
gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
|
|
else
|
|
gtk_widget_set_default_direction(GTK_TEXT_DIR_LTR);
|
|
|
|
ct=gApplication::controlCount();
|
|
for (bucle=0;bucle<ct;bucle++)
|
|
{
|
|
iter=gApplication::controlItem(bucle);
|
|
if (iter->isVisible() && iter->isContainer())
|
|
((gContainer*)iter)->performArrange();
|
|
}
|
|
}
|
|
|
|
void do_iteration(bool do_not_block, bool do_not_sleep)
|
|
{
|
|
struct timespec mywait;
|
|
|
|
gApplication::_loopLevel++;
|
|
|
|
if (do_not_block)
|
|
{
|
|
if (gtk_events_pending ())
|
|
gtk_main_iteration_do (false);
|
|
else if (!do_not_sleep)
|
|
{
|
|
mywait.tv_sec=0;
|
|
mywait.tv_nsec=100000;
|
|
nanosleep(&mywait,NULL);
|
|
}
|
|
}
|
|
else
|
|
gtk_main_iteration_do(true);
|
|
|
|
gApplication::_loopLevel--;
|
|
|
|
if (post_Check) { post_Check=false; GB.CheckPost(); }
|
|
gControl::cleanRemovedControls();
|
|
}
|