Basic clipboard access from Nasal.
- Add platform independent clipboard layer for Nasal access to clipboard (thanks to Hooray for basic code) - Add Windows clipboard access - Add partial X11 clipboard access (only reading from clipboard) - Add fallback clipboard for application internal clipboard if platform not supported - Add some helper functions to FGNasalSys
This commit is contained in:
parent
6110139197
commit
aa9d0e3a8a
8 changed files with 634 additions and 12 deletions
|
@ -5,14 +5,26 @@ set(SOURCES
|
||||||
nasal-props.cxx
|
nasal-props.cxx
|
||||||
NasalPositioned.cxx
|
NasalPositioned.cxx
|
||||||
NasalCanvas.cxx
|
NasalCanvas.cxx
|
||||||
|
NasalClipboard.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
NasalSys.hxx
|
NasalSys.hxx
|
||||||
NasalPositioned.hxx
|
NasalPositioned.hxx
|
||||||
NasalCanvas.hxx
|
NasalCanvas.hxx
|
||||||
|
NasalClipboard.hxx
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
list(APPEND SOURCES ClipboardWindows.cxx)
|
||||||
|
else()
|
||||||
|
find_package(X11)
|
||||||
|
if(X11_FOUND)
|
||||||
|
list(APPEND SOURCES ClipboardX11.cxx)
|
||||||
|
else()
|
||||||
|
list(APPEND SOURCES ClipboardFallback.cxx)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
flightgear_component(Scripting "${SOURCES}" "${HEADERS}")
|
flightgear_component(Scripting "${SOURCES}" "${HEADERS}")
|
||||||
|
|
||||||
|
|
64
src/Scripting/ClipboardFallback.cxx
Normal file
64
src/Scripting/ClipboardFallback.cxx
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// Fallback implementation of clipboard access for Nasal. Copy and edit for
|
||||||
|
// implementing support of other platforms
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 Thomas Geymayer <tomgey@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 of the
|
||||||
|
// License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#include "NasalClipboard.hxx"
|
||||||
|
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a basic clipboard whose contents are only available to FlightGear
|
||||||
|
* itself
|
||||||
|
*/
|
||||||
|
class ClipboardFallback:
|
||||||
|
public NasalClipboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get clipboard contents as text
|
||||||
|
*/
|
||||||
|
virtual std::string getText(Type type)
|
||||||
|
{
|
||||||
|
return type == CLIPBOARD ? _clipboard : _selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set clipboard contents as text
|
||||||
|
*/
|
||||||
|
virtual bool setText(const std::string& text, Type type)
|
||||||
|
{
|
||||||
|
if( type == CLIPBOARD )
|
||||||
|
_clipboard = text;
|
||||||
|
else
|
||||||
|
_selection = text;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::string _clipboard,
|
||||||
|
_selection;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
NasalClipboard::Ptr NasalClipboard::create()
|
||||||
|
{
|
||||||
|
return NasalClipboard::Ptr(new ClipboardFallback);
|
||||||
|
}
|
108
src/Scripting/ClipboardWindows.cxx
Normal file
108
src/Scripting/ClipboardWindows.cxx
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
// Windows implementation of clipboard access for Nasal
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 Thomas Geymayer <tomgey@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 of the
|
||||||
|
// License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#include "NasalClipboard.hxx"
|
||||||
|
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows does only support on clipboard and no selection. We fake also the X11
|
||||||
|
* selection buffer - at least inside FlightGear
|
||||||
|
*/
|
||||||
|
class ClipboardWindows:
|
||||||
|
public NasalClipboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get clipboard contents as text
|
||||||
|
*/
|
||||||
|
virtual std::string getText(Type type)
|
||||||
|
{
|
||||||
|
if( type == CLIPBOARD )
|
||||||
|
{
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
if( !OpenClipboard(NULL) )
|
||||||
|
return data;
|
||||||
|
|
||||||
|
HANDLE hData = GetClipboardData( CF_TEXT );
|
||||||
|
char* buff = (char*)GlobalLock( hData );
|
||||||
|
if (buff)
|
||||||
|
data = buff;
|
||||||
|
GlobalUnlock( hData );
|
||||||
|
CloseClipboard();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return _selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set clipboard contents as text
|
||||||
|
*/
|
||||||
|
virtual bool setText(const std::string& text, Type type)
|
||||||
|
{
|
||||||
|
if( type == CLIPBOARD )
|
||||||
|
{
|
||||||
|
if( !OpenClipboard(NULL) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool ret = true;
|
||||||
|
if( !EmptyClipboard() )
|
||||||
|
ret = false;
|
||||||
|
else if( !text.empty() )
|
||||||
|
{
|
||||||
|
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, text.size() + 1);
|
||||||
|
if( !hGlob )
|
||||||
|
ret = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(GlobalLock(hGlob), (char*)&text[0], text.size() + 1);
|
||||||
|
GlobalUnlock(hGlob);
|
||||||
|
|
||||||
|
if( !SetClipboardData(CF_TEXT, hGlob) )
|
||||||
|
{
|
||||||
|
GlobalFree(hGlob);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseClipboard();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_selection = text;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::string _selection;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
NasalClipboard::Ptr NasalClipboard::create()
|
||||||
|
{
|
||||||
|
return NasalClipboard::Ptr(new ClipboardWindows);
|
||||||
|
}
|
218
src/Scripting/ClipboardX11.cxx
Normal file
218
src/Scripting/ClipboardX11.cxx
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
// X11 implementation of clipboard access for Nasal
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 Thomas Geymayer <tomgey@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 of the
|
||||||
|
// License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#include "NasalClipboard.hxx"
|
||||||
|
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
class ClipboardX11:
|
||||||
|
public NasalClipboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClipboardX11():
|
||||||
|
_display( XOpenDisplay(NULL) ),
|
||||||
|
_window( XCreateSimpleWindow(
|
||||||
|
_display,
|
||||||
|
DefaultRootWindow(_display),
|
||||||
|
0, 0, 1, 1, // dummy dimensions -> window will never be mapped
|
||||||
|
0,
|
||||||
|
0, 0
|
||||||
|
) ),
|
||||||
|
_atom_targets( XInternAtom(_display, "TARGETS", False) ),
|
||||||
|
_atom_primary( XInternAtom(_display, "PRIMARY", False) ),
|
||||||
|
_atom_clipboard( XInternAtom(_display, "CLIPBOARD", False) )
|
||||||
|
{
|
||||||
|
assert(_display);
|
||||||
|
assert(_atom_targets != None);
|
||||||
|
assert(_atom_primary != None);
|
||||||
|
assert(_atom_clipboard != None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get clipboard contents as text
|
||||||
|
*/
|
||||||
|
virtual std::string getText(Type type)
|
||||||
|
{
|
||||||
|
Atom atom_type = (type == CLIPBOARD ? _atom_clipboard : _atom_primary);
|
||||||
|
|
||||||
|
//Request a list of possible conversions
|
||||||
|
XConvertSelection( _display, atom_type, _atom_targets, atom_type,
|
||||||
|
_window, CurrentTime );
|
||||||
|
XFlush(_display);
|
||||||
|
|
||||||
|
Atom requested_type = None;
|
||||||
|
bool sent_request = false;
|
||||||
|
|
||||||
|
for(int cnt = 0; cnt < 5;)
|
||||||
|
{
|
||||||
|
XEvent event;
|
||||||
|
XNextEvent(_display, &event);
|
||||||
|
|
||||||
|
if( event.type == SelectionNotify )
|
||||||
|
{
|
||||||
|
Atom target = event.xselection.target;
|
||||||
|
if(event.xselection.property == None)
|
||||||
|
{
|
||||||
|
if( target == _atom_targets )
|
||||||
|
// If TARGETS can not be converted no selection is available
|
||||||
|
break;
|
||||||
|
|
||||||
|
SG_LOG
|
||||||
|
(
|
||||||
|
SG_NASAL,
|
||||||
|
SG_WARN,
|
||||||
|
"ClipboardX11::getText: Conversion failed: "
|
||||||
|
"target=" << getAtomName(target)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//If we're being given a list of targets (possible conversions)
|
||||||
|
if(target == _atom_targets && !sent_request)
|
||||||
|
{
|
||||||
|
sent_request = true;
|
||||||
|
requested_type = XA_STRING; // TODO select other type
|
||||||
|
XConvertSelection( _display, atom_type, requested_type, atom_type,
|
||||||
|
_window, CurrentTime );
|
||||||
|
}
|
||||||
|
else if(target == requested_type)
|
||||||
|
{
|
||||||
|
Property prop = readProperty(_window, atom_type);
|
||||||
|
if( prop.format != 8 )
|
||||||
|
{
|
||||||
|
SG_LOG
|
||||||
|
(
|
||||||
|
SG_NASAL,
|
||||||
|
SG_WARN,
|
||||||
|
"ClipboardX11::getText: can only handle 8-bit data (is "
|
||||||
|
<< prop.format << "-bit) -> retry "
|
||||||
|
<< cnt++
|
||||||
|
);
|
||||||
|
XFree(prop.data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result((const char*)prop.data, prop.num_items);
|
||||||
|
XFree(prop.data);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SG_LOG
|
||||||
|
(
|
||||||
|
SG_NASAL,
|
||||||
|
SG_WARN,
|
||||||
|
"ClipboardX11::getText: wrong target: " << getAtomName(target)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SG_LOG
|
||||||
|
(
|
||||||
|
SG_NASAL,
|
||||||
|
SG_WARN,
|
||||||
|
"ClipboardX11::getText: unexpected XEvent: " << event.type
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set clipboard contents as text
|
||||||
|
*/
|
||||||
|
virtual bool setText(const std::string& text, Type type)
|
||||||
|
{
|
||||||
|
SG_LOG
|
||||||
|
(
|
||||||
|
SG_NASAL,
|
||||||
|
SG_ALERT,
|
||||||
|
"ClipboardX11::setText: not yet implemented!"
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Display *_display;
|
||||||
|
Window _window;
|
||||||
|
Atom _atom_targets,
|
||||||
|
_atom_primary,
|
||||||
|
_atom_clipboard;
|
||||||
|
|
||||||
|
struct Property
|
||||||
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
int format, num_items;
|
||||||
|
Atom type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all data from a property
|
||||||
|
Property readProperty(Window w, Atom property)
|
||||||
|
{
|
||||||
|
Atom actual_type;
|
||||||
|
int actual_format;
|
||||||
|
unsigned long nitems;
|
||||||
|
unsigned long bytes_after;
|
||||||
|
unsigned char *ret=0;
|
||||||
|
|
||||||
|
int read_bytes = 1024;
|
||||||
|
|
||||||
|
//Keep trying to read the property until there are no
|
||||||
|
//bytes unread.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if( ret )
|
||||||
|
XFree(ret);
|
||||||
|
|
||||||
|
XGetWindowProperty
|
||||||
|
(
|
||||||
|
_display, w, property, 0, read_bytes, False, AnyPropertyType,
|
||||||
|
&actual_type, &actual_format, &nitems, &bytes_after,
|
||||||
|
&ret
|
||||||
|
);
|
||||||
|
|
||||||
|
read_bytes *= 2;
|
||||||
|
} while( bytes_after );
|
||||||
|
|
||||||
|
Property p = {ret, actual_format, nitems, actual_type};
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getAtomName(Atom atom)
|
||||||
|
{
|
||||||
|
return atom == None ? "None" : XGetAtomName(_display, atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
NasalClipboard::Ptr NasalClipboard::create()
|
||||||
|
{
|
||||||
|
return NasalClipboard::Ptr(new ClipboardX11);
|
||||||
|
}
|
131
src/Scripting/NasalClipboard.cxx
Normal file
131
src/Scripting/NasalClipboard.cxx
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
// X11 implementation of clipboard access for Nasal
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 Thomas Geymayer <tomgey@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 of the
|
||||||
|
// License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "NasalClipboard.hxx"
|
||||||
|
#include "NasalSys.hxx"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nasal wrappers for setting/getting clipboard text
|
||||||
|
*/
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static NasalClipboard::Type parseType(naContext c, int argc, naRef* args, int i)
|
||||||
|
{
|
||||||
|
if( argc > i )
|
||||||
|
{
|
||||||
|
if( !naIsString(args[i]) )
|
||||||
|
naRuntimeError(c, "clipboard: invalid arg (not a string)");
|
||||||
|
|
||||||
|
std::string type_str( naStr_data(args[i]) );
|
||||||
|
boost::to_upper(type_str);
|
||||||
|
|
||||||
|
if( type_str == "CLIPBOARD" )
|
||||||
|
return NasalClipboard::CLIPBOARD;
|
||||||
|
else if( type_str == "PRIMARY" || type_str == "SELECTION" )
|
||||||
|
return NasalClipboard::PRIMARY;
|
||||||
|
else
|
||||||
|
naRuntimeError(c, "clipboard: unknown clipboard type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NasalClipboard::CLIPBOARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static naRef f_setClipboardText(naContext c, naRef me, int argc, naRef* args)
|
||||||
|
{
|
||||||
|
if( argc < 1 || argc > 2 )
|
||||||
|
naRuntimeError( c, "clipboard.setText() expects 1 or 2 arguments: "
|
||||||
|
"text, [, type = \"CLIPBOARD\"]" );
|
||||||
|
|
||||||
|
if( !naIsString(args[0]) )
|
||||||
|
naRuntimeError(c, "clipboard.setText() invalid arg (arg 0 not a string)");
|
||||||
|
|
||||||
|
return
|
||||||
|
naNum
|
||||||
|
(
|
||||||
|
NasalClipboard::getInstance()->setText( naStr_data(args[0]),
|
||||||
|
parseType(c, argc, args, 1) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static naRef f_getClipboardText(naContext c, naRef me, int argc, naRef* args)
|
||||||
|
{
|
||||||
|
if( argc > 1 )
|
||||||
|
naRuntimeError(c, "clipboard.getText() accepts max 1 arg: "
|
||||||
|
"[type = \"CLIPBOARD\"]" );
|
||||||
|
|
||||||
|
const std::string& text =
|
||||||
|
NasalClipboard::getInstance()->getText(parseType(c, argc, args, 0));
|
||||||
|
|
||||||
|
// TODO create some nasal helper functions (eg. stringToNasal)
|
||||||
|
// some functions are available spread over different files (eg.
|
||||||
|
// NasalPositioned.cxx)
|
||||||
|
return naStr_fromdata(naNewString(c), text.c_str(), text.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Table of extension functions, terminate with 0,0
|
||||||
|
static struct {const char* name; naCFunction func; } funcs[] = {
|
||||||
|
{ "setText", f_setClipboardText },
|
||||||
|
{ "getText", f_getClipboardText },
|
||||||
|
{ 0,0 } // TERMINATION
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
NasalClipboard::Ptr NasalClipboard::_clipboard;
|
||||||
|
naRef NasalClipboard::_clipboard_hash;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
NasalClipboard::~NasalClipboard()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void NasalClipboard::init(FGNasalSys *nasal)
|
||||||
|
{
|
||||||
|
_clipboard = create();
|
||||||
|
_clipboard_hash = naNewHash(nasal->context());
|
||||||
|
|
||||||
|
nasal->globalsSet("clipboard", _clipboard_hash);
|
||||||
|
|
||||||
|
for(size_t i=0;funcs[i].name;i++)
|
||||||
|
{
|
||||||
|
nasal->hashset
|
||||||
|
(
|
||||||
|
_clipboard_hash,
|
||||||
|
funcs[i].name,
|
||||||
|
naNewFunc(nasal->context(), naNewCCode(nasal->context(), funcs[i].func))
|
||||||
|
);
|
||||||
|
|
||||||
|
SG_LOG(SG_NASAL, SG_DEBUG, "Adding clipboard function: " << funcs[i].name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
NasalClipboard::Ptr NasalClipboard::getInstance()
|
||||||
|
{
|
||||||
|
return _clipboard;
|
||||||
|
}
|
72
src/Scripting/NasalClipboard.hxx
Normal file
72
src/Scripting/NasalClipboard.hxx
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Clipboard access for Nasal
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 Thomas Geymayer <tomgey@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 of the
|
||||||
|
// License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#ifndef NASAL_CLIPOARD_HXX_
|
||||||
|
#define NASAL_CLIPOARD_HXX_
|
||||||
|
|
||||||
|
#include <simgear/nasal/nasal.h>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class FGNasalSys;
|
||||||
|
class NasalClipboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
/// Standard clipboard as supported by nearly all operating systems
|
||||||
|
CLIPBOARD,
|
||||||
|
|
||||||
|
/// X11 platforms support also a mode called PRIMARY selection which
|
||||||
|
/// contains the current (mouse) selection and can typically be inserted
|
||||||
|
/// via a press on the middle mouse button
|
||||||
|
PRIMARY
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<NasalClipboard> Ptr;
|
||||||
|
|
||||||
|
virtual std::string getText(Type type = CLIPBOARD) = 0;
|
||||||
|
virtual bool setText( const std::string& text,
|
||||||
|
Type type = CLIPBOARD ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the clipboard and puts all the extension functions into a new
|
||||||
|
* "clipboard" namespace.
|
||||||
|
*/
|
||||||
|
static void init(FGNasalSys *nasal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get clipboard platform specific instance
|
||||||
|
*/
|
||||||
|
static Ptr getInstance();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static Ptr _clipboard;
|
||||||
|
static naRef _clipboard_hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation supplied by actual platform implementation
|
||||||
|
*/
|
||||||
|
static Ptr create();
|
||||||
|
|
||||||
|
virtual ~NasalClipboard() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* NASAL_CLIPOARD_HXX_ */
|
|
@ -28,11 +28,13 @@
|
||||||
#include "NasalSys.hxx"
|
#include "NasalSys.hxx"
|
||||||
#include "NasalPositioned.hxx"
|
#include "NasalPositioned.hxx"
|
||||||
#include "NasalCanvas.hxx"
|
#include "NasalCanvas.hxx"
|
||||||
|
#include "NasalClipboard.hxx"
|
||||||
|
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
#include <Main/util.hxx>
|
#include <Main/util.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
|
|
||||||
|
|
||||||
using std::map;
|
using std::map;
|
||||||
|
|
||||||
static FGNasalSys* nasalSys = 0;
|
static FGNasalSys* nasalSys = 0;
|
||||||
|
@ -101,6 +103,20 @@ FGNasalSys::FGNasalSys()
|
||||||
_callCount = 0;
|
_callCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utility. Sets a named key in a hash by C string, rather than nasal
|
||||||
|
// string object.
|
||||||
|
void FGNasalSys::hashset(naRef hash, const char* key, naRef val)
|
||||||
|
{
|
||||||
|
naRef s = naNewString(_context);
|
||||||
|
naStr_fromdata(s, (char*)key, strlen(key));
|
||||||
|
naHash_set(hash, s, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGNasalSys::globalsSet(const char* key, naRef val)
|
||||||
|
{
|
||||||
|
hashset(_globals, key, val);
|
||||||
|
}
|
||||||
|
|
||||||
naRef FGNasalSys::call(naRef code, int argc, naRef* args, naRef locals)
|
naRef FGNasalSys::call(naRef code, int argc, naRef* args, naRef locals)
|
||||||
{
|
{
|
||||||
return callMethod(code, naNil(), argc, args, locals);
|
return callMethod(code, naNil(), argc, args, locals);
|
||||||
|
@ -170,15 +186,6 @@ FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility. Sets a named key in a hash by C string, rather than nasal
|
|
||||||
// string object.
|
|
||||||
void FGNasalSys::hashset(naRef hash, const char* key, naRef val)
|
|
||||||
{
|
|
||||||
naRef s = naNewString(_context);
|
|
||||||
naStr_fromdata(s, (char*)key, strlen(key));
|
|
||||||
naHash_set(hash, s, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The get/setprop functions accept a *list* of strings and walk
|
// The get/setprop functions accept a *list* of strings and walk
|
||||||
// through the property tree with them to find the appropriate node.
|
// through the property tree with them to find the appropriate node.
|
||||||
// This allows a Nasal object to hold onto a property path and use it
|
// This allows a Nasal object to hold onto a property path and use it
|
||||||
|
@ -551,7 +558,8 @@ void FGNasalSys::init()
|
||||||
|
|
||||||
initNasalPositioned(_globals, _context, _gcHash);
|
initNasalPositioned(_globals, _context, _gcHash);
|
||||||
initNasalCanvas(_globals, _context, _gcHash);
|
initNasalCanvas(_globals, _context, _gcHash);
|
||||||
|
NasalClipboard::init(this);
|
||||||
|
|
||||||
// Now load the various source files in the Nasal directory
|
// Now load the various source files in the Nasal directory
|
||||||
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
|
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
|
||||||
loadScriptDirectory(nasalDir);
|
loadScriptDirectory(nasalDir);
|
||||||
|
|
|
@ -114,6 +114,16 @@ public:
|
||||||
|
|
||||||
void deleteModule(const char* moduleName);
|
void deleteModule(const char* moduleName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set member of specified hash to given value
|
||||||
|
*/
|
||||||
|
void hashset(naRef hash, const char* key, naRef val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set member of globals hash to given value
|
||||||
|
*/
|
||||||
|
void globalsSet(const char* key, naRef val);
|
||||||
|
|
||||||
naRef call(naRef code, int argc, naRef* args, naRef locals);
|
naRef call(naRef code, int argc, naRef* args, naRef locals);
|
||||||
|
|
||||||
naRef callMethod(naRef code, naRef self, int argc, naRef* args, naRef locals);
|
naRef callMethod(naRef code, naRef self, int argc, naRef* args, naRef locals);
|
||||||
|
@ -168,7 +178,6 @@ private:
|
||||||
void loadPropertyScripts(SGPropertyNode* n);
|
void loadPropertyScripts(SGPropertyNode* n);
|
||||||
void loadScriptDirectory(simgear::Dir nasalDir);
|
void loadScriptDirectory(simgear::Dir nasalDir);
|
||||||
void addModule(string moduleName, simgear::PathList scripts);
|
void addModule(string moduleName, simgear::PathList scripts);
|
||||||
void hashset(naRef hash, const char* key, naRef val);
|
|
||||||
void logError(naContext);
|
void logError(naContext);
|
||||||
naRef parse(const char* filename, const char* buf, int len);
|
naRef parse(const char* filename, const char* buf, int len);
|
||||||
naRef genPropsModule();
|
naRef genPropsModule();
|
||||||
|
|
Loading…
Add table
Reference in a new issue