first try

This commit is contained in:
Stefan Salewski 2017-07-12 18:24:32 +02:00
commit 0ea089d432
21 changed files with 108883 additions and 2 deletions

494
README.adoc Normal file
View file

@ -0,0 +1,494 @@
:experimental:
:imagesdir: http://ssalewski.de/tmp
:source-highlighter: pygments
(c) Stefan Salewski +
2017
= High level GTK3 bindings for the Nim programming language
NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf and other Nim and GTK/Gnome developers.
The combinatorics module was kindly provided by R. Behrends.
This repository contains bindings from the Nim programming language to the GTK3 GUI library and related libraries. (With minimal fixes
it should also work for upcoming GTK4.)
https://nim-lang.org/[Nim] is a modern universal programming language.
https://www.gtk.org/[GTK], also known as the Gimp Tool Kit and now sometimes also called Gnome Tool Kit, is a Graphical User Interface library.
NOTE: Later we will insert at this location a nice picture of a fancy Nim GTK3 GUI. Such a picture is fine to attract users and indeed is a good motivation.
But such pictures are no real evidence for the quality of a GUI toolkit -- the concrete example may look nice, while the toolkit
looks much worse in other environments and offers by far not all that what is needed in real life.
While GTK was initially designed and advertised as cross platform GUI toolkit, it is currently mostly used on Linux and other Unix like operation systems.
Most Linux distributions include it, and some use it for their default desktop environment, often with the Gnome environment or other window managers.
While GTK2 applications like GIMP are still used on Windows, there seems to exist currently only very few GTK3 applications for Windows or MacOS.
When you develop primary free open source software for Linux or other Unix like Operating Systems, then GTK3 is a good choice for you. With some
effort you should be even able to port your application to the proprietary Windows or MacOS operating systems. But when your primary target platforms
are Windows and MacOS and you desire a real native look and feel there, then you may find better suited ones in the Nim software repository.
Also, when you only need a minimal restricted GUI which is very easy to install on Windows and MacOSX, then you may find better suited packages
in the Nim package repository. Android OS is currently not supported by GTK at all.
While low level Nim bindings for GTK3 are already available since a few years, this one is an attempt to
provide real high level bindings with full type safety, full Garbage Collector (GC) support and an idiomatic
application interface.
The low level bindings available at https://github.com/ngtk3 where generated with the Nim tool c2nim directly from the C header files, are already tested
with some applications (https://github.com/ngtk3/NEd[NEd Nim Editor], https://github.com/StefanSalewski/nim-chess3[Chess Game])
and generally work fine. Indeed missing Garbage Collector support is generally not really a problem, as widgets are generally
put into containers and were automatically deleted together with its parents due to GTK's reference counting.
Still there can be some demand for really high level bindings -- so this repository tries to provide them.
High level GTK3 bindings, as available for many other programming languages like Python, Ruby or D already,
would have these advantages:
* full Garbage Collector support -- you should never have to free resources manually
* Widgets are Nim objects, so inheritance and sub-classing can be used
* full type safety -- no needs for casts or other unsafe and dangerous operations
These high level bindings are based on GObject-Inrospection, an XML based database like interface description. Compared to the C header
files this description gives us more and deeper information about data types and function calls, for example ownership transfer of objects and
in or out direction of procedure variables, which makes writing the glue code much easier.
And it should work with no or minimal
modifications also for the upcoming GTK4.
Unfortunately there are also some drawbacks:
* The Application Programmer Interface (API) will be different from what is known from C API, so using C examples or C tutorials is not really straight forward
* The high level source code will differ from available C examples, so there would be a big demand for tutorials
* We need a lot of glue code, which has much room for bugs. So much testing is necessary.
* There is some overhead due to indirect calls, leading to some code size increase and minimal
performance loss.
NOTE: The new package name is "gintro", short for GObject-Introspection. The previous name was nim-gi, but the hyphen is deprecated for package names, as is the
nim prefix.
== Current state of these bindings
We are still in an early stage, but it is already more than a proof of concept. GTK and related libraries have many thousand of
callable functions and nearly as many data types. Testing all that is nearly impossible for a small team with limited resources.
The initial approach was to generate low level
bindings, which looked similar to the ones generated by the c2nim tool from the C headers. After that was done, we have associated all
the C structs and GObject data types with Nim proxy objects. A well defined relation between these proxy object and the low level C data types
should ensure fully automatic garbage collection. This is supported by smart type conversion, for example C strings returned by glib library
are assigned to newly created Nim strings, while the memory of the C strings is automatically freed. For most cases this seems to work. But there
exists a few more complicated cases, for example functions may return whole arrays of C strings or other non elementary data types,
or function arguments or results may be so called glists,
list structures of glib library. These cases can not be processed automatically but needs carefully manual investigations. And there may be still functions and data
types missing: GObject Introspection query gives us many thousand lines of Nim interface code, and it is not really obvious if and what is missing.
Some functions and data types are missing for sure -- at least some low level ones, which are considered unneeded for high level bindings by GObject-Introspection.
But maybe more is missing, we have to investigate that. Until now these bindings have been tested only for 64 bit Linux systems with GTK 3.22.
These basic libraries are already partly tested:
* GLib
* GObject
* GModule
* xlib
* Gio
* Atk
* Pango
* cairo
* GdkPixbuf
* Rsvg
* Gdk
* Gtk
In best case it should be possible to add more GObject based libraries to this list without larger modifications of the generator source code.
Unfortunately the cairo bindings provided by GObject-Introspectin are only a minimal stub -- later we will have to extend it manually.
== How to try it out
Of course you will need a working Nim installation with a recent compiler version and you have to ensure that GTK and related libraries are installed on your system. For some Linux
distributions which provide mainly pre-compiled software you may have to also install some GTK related developer files.
This package now supports the nimble package manager, so ideally a plain "nimble install gintro" should do. But as this package does not
only provide some plain text files, but uses GObject-Introspection database query on your local computer to generate
binding files exactly matching your system, that does not work currently. We have to download the files, compile and execute
the gen.nim generator program and finally to install the generates binding modules on your computer as a nimble package.
These instructions should be enough for that:
----
cd /tmp
git clone https://github.com/stefansalewski/gintro
cd gintro
nimble prepare
nimble install
----
NOTE: Nimble prepare should run for about 20 seconds, it compiles and executes the generator program gen.nim.
Unfortunately we can not guarantee that the generator command will be able to really build all the
desired modules. The built process highly depends on your OS and installed GTK version. For 64 bit Linux systems
with GTK 3.22 and all required dependencies installed it should work. For never GTK versions it may fail, when that GTK
release introduces for example new unknown data types like array containers. In that case manual fixes may be necessary.
The GObject Introspection based built process generates bindings customized to the OS where the generator is executed,
so for older GTK releases or a 32 bit system different files are created. Later we may also provide pre-generated
files for various OS and GTK versions, but building locally is preferred when possible.
Now you can built app0 and launch it:
----
cd /tmp/gintro/examples/
nim c app0.nim
./app0
----
== A few basic examples
GTK3 programs can use still the old GTK2 design, where you first initialize the GTK library, create your widgets and finally enter the GTK main loop.
This style is still used in many tutorials as in http://zetcode.com/gui/gtk2/[Zetcode tutorial] or in the GTK book of Andrew Krause.
Or you can use the new GTK3 App style, this is generally recommended by newer original GTK documentation.
Unfortunately the GTK3 original documentation is mostly restricted to the GTK3 API documentation, which is generally very good, but makes
it not very easy for beginners to start with GTK. API docs and some basic introduction is available here:
* https://www.gnome.org/
* https://www.gtk.org/
* https://developer.gnome.org/
* https://developer.gnome.org/gtk3/stable/
* https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.5
* https://developer.gnome.org/gnome-devel-demos/stable/c.html.en
TIP: If you should decide to continue developing software with GTK, then you should consider installing the so called
devhelp tool. It gives you easy and fast access to the API docs. For example, if you want to use a Button Widget in your
GUI and wants to learn more about related functions and signals, you just enter "Button" in that tool and are guided to
all the relevant information.
We start with a minimal traditional old style example, which should be familiar to most of us:
[source,nim]
----
# nim c t0.nim
import gtk
proc bye(w: Window) =
mainQuit()
echo "Bye..."
proc main =
gtk.init()
let window = newWindow()
window.title = "First Test"
window.connect("destroy", bye)
window.showAll
gtk.main()
main()
----
This is the traditional layout of GTK2 programs. When using this style then it is important to initialize the GTK library by calling gtk.init()
at the very beginning. Then we create the desired widgets, connect signals, show all widgets and finally enter the GTK main loop
by calling gtk.main. About connecting signals we will learn more soon, for now it is only important that we have to connect to
the destroy signal here to enable the user to terminate program execution by clicking the window close button.
Now a really minimal but complete App style example, which displays an empty window.
NOTE: The source text of all these examples is contained in the examples directory. Unfortunately github
seems to not allow to include that sources directly into this document, so there may be minimal
differences between the source code displayed here and the sources in examples directory.
[source,nim]
----
# app0.nim -- minimal application style example
# nim c app0.nim
import gtk
import gio except Application, newApplication # we want to use GTK application
#from gio import ApplicationFlags, scActivate, run
proc activate(app: Application) =
let window = newApplicationWindow(app)
window.title = "GTK3 & Nim"
window.defaultSize = (200, 200)
showAll(window)
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", activate)
discard run(app)
main()
----
In the main proc we create a new application and connect the activate signal to our activate proc, which then creates and displays
the still empty window. For this program we need the gtk module and also some procs and types from gio module. As both modules
have a data type called Application (gtk extends indeed the gio.Application) we can either qualify the Application data type and its new proc
with gtk prefix, or as we did here, exclude that from gio imports. Another solution would be to import from gio only what is really needed.
The source code of this minimal example is stored in the examples directory, you may cd into it and type "nim c app0.nim" to create
the executable. (Well not yet, as we provide no real nimble install. Copy app0.nim to nim_gi directory where the bindings live, or
create symlinks for now.)
Various ways to set widget parameters are supported -- the number 1 to 6 refer to the comment below:
//. Setting widget parameters
[source,nim]
----
setDefaultSize(window, 200, 200) # <1>
gtk.setDefaultSize(window, 200, 200) # <2>
window.setDefaultSize(200, 200) # <3>
window.setDefaultSize(width = 200, height = 200) # <4>
window.defaultSize = (200, 200) # <5>
window.defaultSize = (width: 200, height: 200) # <6>
----
<1> proc call syntax
<2> optional qualified with module name prefix
<3> method call syntax
<4> named parameters
<5> tupel assignment
<6> tupel assignment with named members
Well, that empty window is really not very interesting. The GTK and Gnome team provides some GTK examples at https://developer.gnome.org/gnome-devel-demos/.
The https://developer.gnome.org/gnome-devel-demos/3.22/c.html.en[C demos] seems to be most actual and complete, and are easy to port to Nim. So we start with these,
but if you are familiar with the other listed languages, then you can try to port them to Nim as well. Let us start with https://developer.gnome.org/gnome-devel-demos/3.22/button.c.html.en
-- it is still short and easy to understand, but shows already some interesting topics.
image::NimGTK3Button.png[]
The C code looks like this:
[source,c]
----
#include <gtk/gtk.h>
/*This is the callback function. It is a handler function which
reacts to the signal. In this case, it will cause the button label's
string to reverse.*/
static void
button_clicked (GtkButton *button,
gpointer user_data)
{
const char *old_label;
char *new_label;
old_label = gtk_button_get_label (button);
new_label = g_utf8_strreverse (old_label, -1);
gtk_button_set_label (button, new_label);
g_free (new_label);
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
/*Create a window with a title and a default size*/
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "GNOME Button");
gtk_window_set_default_size (GTK_WINDOW (window), 250, 50);
/*Create a button with a label, and add it to the window*/
button = gtk_button_new_with_label ("Click Me");
gtk_container_add (GTK_CONTAINER (window), button);
/*Connecting the clicked signal to the callback function*/
g_signal_connect (GTK_BUTTON (button),
"clicked",
G_CALLBACK (button_clicked),
G_OBJECT (window));
gtk_widget_show_all (window);
}
int
main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
----
Converting it to Nim is straight forward with some basic C and Nim knowledge, and Nim does not force us
to convert its shape into all the classes known from pure object orientated languages. We can either use the
Nim tool c2nim to help us with the conversion, or do it manually. Indeed c2nim can be very helpful by
converting C sources to Nim. Most of the time it works well. Personally I generally pre-process C files, for example
by removing too strange macros and defines, or by replacing strange constructs, like C for loops, to simpler
ones like while loops. Then I apply c2nim to the C file and finally manually compare the result line by line and
fine tune the Nim code. But for this short source text we may do all that manually and finally get something like
this:
[source,nim]
----
# nim c button.nim
import gtk, glib
import gio except Application, newApplication
proc buttonClicked (button: Button) =
button.label = utf8Strreverse(button.label, -1)
proc activate (app: Application) =
let window = newApplicationWindow(app)
window.title = "GNOME Button"
window.defaultSize = (250, 50)
let button = newButton("Click Me")
window.add(button)
button.connect("clicked", buttonClicked)
window.showAll
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", activate)
discard app.run
main()
----
Again we have the basic shape already known from app0.nim example: Main proc creates the application, connect
to the activate signal and finally runs the application. When GTK launches the application and emits the activate signal, then
our activate proc is called, which creates a main window containing a button widget. That button is again connected with a
signal, in this case named clicked. That signal is emitted by GTK whenever that button is clicked with the mouse and results
in a call of our provided buttonClicked() proc. The procs connected to signals are called callbacks and generally got the widget
on which the signal was emitted as first parameter. They can also get a second optional parameter of arbitrary type -- we will
see that in a later example. This callback here gets only the button itself as parameter, and it's task is to reverse the
text displayed by the button. Not very interesting basically, but we are indeed using the glib function utf8Strreverse()
for this task. While that function internally works with cstrings, and in C we have to free the memory of the returned cstring,
in our Nim example that is done automatically by Nim's Garbage Collector. When you compare our example carefully with the C code,
then you may notice a difference. The C code passes the window containing the button as an additional parameter to the
callback function, but that parameter is not really used. We simple ignore it here, as it is not used at all.
//and I assume that passing a widget in this way in our nim code
//may not work already currently. Fortunately widgets as optional parameter are not often needed, and we will try to make that
//working soon...
In one of the following examples you will learn how passing (nearly) arbitrary parameters in a type safe way is done.
Another difference is, that the C code returns an integer status value returned by g_application_run() to the OS. We
could do the same by using the quit() proc of Nim's OS module, but as that would give us no additional benefit, we simply ignore it.
TIP: The command nim c sourcetext.nim generates an executable which contains code for runtime checks and debugging,
which increases executable size and decreases performance.
After you have tested your software carefully, you may give the additional parameter -d:release to avoid this. For the gcc backend
you may additional enable link time optimization (LTO), which reduces executable size further. To enable LTO. you may put
a nim.cfg file in your sources directory with content like
----
path:"$projectdir"
nimcache:"/tmp/$projectdir"
gcc.options.speed = "-march=native -O3 -flto -fstrict-aliasing"
----
With that optimization, your executable sizes should be in the range of about 50 kilobyte only!
=== Optional, type safe parameters for callbacks
The next example shows, how we can pass (nearly) arbitrary parameters to our connect procs.
We pass a string, an object from the stack, a reference to an object allocated on the heap
and finally a widget (in this case the application window itself, you may also try passing
another button). As the main window itself is a so called GTK bin and can contain only one
child widget, we create a container widget, a vertical box in this case, fill that box with
some buttons, and add that button to the window.
Compile and start this example from the command line and watch what
happens when you click on the buttons.
[source,nim]
----
# nim c connect_args.nim
import gtk, glib
import gio except Application, newApplication
type
O = object
i: int
proc b1Callback(button: Button; str: string) =
echo str
proc b2Callback(button: Button; o: O) =
echo "Value of field i in object o = ", o.i
proc b3Callback(button: Button; r: ref O) =
echo "Value of field i in ref to object O = ", r.i
proc b4Callback(button: Button; w: ApplicationWindow) =
if w.title == "Nim with GTK3":
w.title = "GTK3 with Nim"
else:
w.title = "Nim with GTK3"
proc activate (app: Application) =
var o: O
var r: ref O
new r
o.i = 1234567
r.i = 7654321
let window = newApplicationWindow(app)
let box = newBox(Orientation.vertical, 0)
window.title = "Parameters for callbacks"
let b1 = newButton("Nim with GTK3")
let b2 = newButton("Passing an object from stack")
let b3 = newButton("Passing an object from heap")
let b4 = newButton("Passing a Widget")
b1.connect("clicked", b1Callback, "is much fun.")
b2.connect("clicked", b2Callback, o)
b3.connect("clicked", b3Callback, r)
b4.connect("clicked", b4Callback, window)
box.add(b1)
box.add(b2)
box.add(b3)
box.add(b4)
window.add(box)
window.showAll
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", activate)
discard app.run
main()
----
To prove type safety, we may modify one of the callback procs and watch the compiler output:
[source,c]
----
proc b1Callback(button: Button; str: int) =
discard # echo str
----
----
connect_args.nim(37, 5) template/generic instantiation from here
gtk.nim(-15021, 10) Error: type mismatch: got (ref Button:ObjectType, string)
but expected one of:
proc b1Callback(button: Button; str: int)
----
It may be not always really obvious what the compiler wants to tell us, but at least we
are told that it got a string and expected an int.
Currently the connect function is realized by a Nim type safe macro. Connect accepts two or three
arguments -- the widget, the signal name and the optional argument. When the optional argument
is a ref (reference to objects on the heap) then it is passed as a reference, otherwise a deep copy
of the argument is passed. For the above code this means, that r and the window are passed
as references, while the string and the stack object are deep copied. Currently it is not possible
to release the memory of passed arguments again. This should be no real problem, as in most
cases no arguments are passed at all, and when arguments are passed, then they are general
small in size like plain numbers or strings, or maybe references to widgets which could not be freed
at all, as they are part of the GUI. Later we may add more variants of that connect macro.
NOTE: Navigation can be hard for beginners. You may have basic knowledge of GTK and want
to build a GUI for your application. But how to find what you need. Well, we offer no separate
automatically generated API documentation currently, as that is not really helpful. In most cases
it is easy to just guess Nim symbol names, proc parameters and all that. Using a smart editor
with good nimsuggest support further supports navigation -- for example NEd shows us
all the needed proc parameters when we move the cursor on a proc name, or we press CTRL-W and jump
to the definition of that symbol. For unknown stuff the original C function name is often a good starting point.
Assume you don't know much about GTK's buttons, but you know that you want to have a Button in
your GUI application. GTK generally offers generator functions containing the string "new" in their name.
So it is easy to guess that there exists a C function named "gtk_button_new". That name is also
contained in the bindings files, in this case in gtk.nim. So we open that file in a text editor and search for
that term. So it is really easy to find first starting points for related procs and data types. Most data types
are located near by their related functions, so you should be able to find all relevant information fast.
Remember the GTK devhelp tool, and use also grep or the nim-grep variant.
NOTE: Related work: https://github.com/jdmansour/nim-smartgi

View file

@ -1,2 +0,0 @@
# gintro
High level GObject-Introspection based GTK3 bindings for Nim language

18
examples/app0.nim Normal file
View file

@ -0,0 +1,18 @@
# app0.nim -- minimal application style example
# nim c app0.nim
import gintro/gtk
import gintro/gio except Application, newApplication # we want to use GTK application
#from gintro/gio import ApplicationFlags, scActivate, run
proc activate(app: Application) =
let window = newApplicationWindow(app)
window.title = "GTK3 & Nim"
window.defaultSize = (200, 200)
showAll(window)
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", activate)
discard run(app)
main()

23
examples/button.nim Normal file
View file

@ -0,0 +1,23 @@
# nim c button.nim
import gintro/[gtk, glib]
import gintro/gio except Application, newApplication
proc buttonClicked (button: Button) =
button.label = utf8Strreverse(button.label, -1)
proc activate (app: Application) =
let window = newApplicationWindow(app)
window.title = "GNOME Button"
window.defaultSize = (250, 50)
let button = newButton("Click Me")
window.add(button)
button.connect("clicked", buttonClicked)
window.showAll
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", activate)
discard app.run
main()

54
examples/connect_args.nim Normal file
View file

@ -0,0 +1,54 @@
# nim c connect_args.nim
import gintro/[gtk, glib]
import gintro/gio except Application, newApplication
type
O = object
i: int
proc b1Callback(button: Button; str: string) =
echo str
proc b2Callback(button: Button; o: O) =
echo "Value of field i in object o = ", o.i
proc b3Callback(button: Button; r: ref O) =
echo "Value of field i in ref to object O = ", r.i
proc b4Callback(button: Button; w: ApplicationWindow) =
if w.title == "Nim with GTK3":
w.title = "GTK3 with Nim"
else:
w.title = "Nim with GTK3"
proc activate (app: Application) =
var o: O
var r: ref O
new r
o.i = 1234567
r.i = 7654321
let window = newApplicationWindow(app)
let box = newBox(Orientation.vertical, 0)
window.title = "Parameters for callbacks"
let b1 = newButton("Nim with GTK3")
let b2 = newButton("Passing an object from stack")
let b3 = newButton("Passing an object from heap")
let b4 = newButton("Passing a Widget")
b1.connect("clicked", b1Callback, "is much fun.")
b2.connect("clicked", b2Callback, o)
b3.connect("clicked", b3Callback, r)
b4.connect("clicked", b4Callback, window)
box.add(b1)
box.add(b2)
box.add(b3)
box.add(b4)
window.add(box)
window.showAll
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", activate)
discard app.run
main()

16
examples/t0.nim Normal file
View file

@ -0,0 +1,16 @@
# nim c t0.nim
import gintro/gtk
proc bye(w: Window) =
mainQuit()
echo "Bye..."
proc main =
gtk.init()
let window = newWindow()
window.title = "First Test"
window.connect("destroy", bye)
window.showAll
gtk.main()
main()

65
gintro.nimble Normal file
View file

@ -0,0 +1,65 @@
# Package
version = "0.1.0"
author = "Stefan Salewski"
description = "High level GObject-Introspection based GTK3 bindings"
license = "MIT"
skipDirs = @["tests"]
# Dependencies
requires "nim >= 0.17.0"
when defined(nimdistros):
import distros
if detectOs(Ubuntu) or detectOs(Debian):
foreignDep "libgtk-3-dev"
elif detectOs(Gentoo):
foreignDep "gtk+" # can we specify gtk3?
#else: we don't know the names for all the other distributions
# foreignDep "openssl"
import ospaths
proc prep =
let this = thisDir()
let td = getTempDir()
cd(td)
let wd = "gintrosalewski"
if dirExists(wd):
quit("gintro: tmp directory already exists!")
mkDir(wd)
cd(wd)
mkDir("ngtk3")
cd("ngtk3")
exec("git clone https://github.com/ngtk3/nim-glib")
exec("git clone https://github.com/ngtk3/nim-gobject")
exec("git clone https://github.com/ngtk3/nim-gir")
cpFile(this / "tests" / "gen.nim", td / wd / "gen.nim")
cpFile(this / "tests" / "combinatorics.nim", td / wd / "combinatorics.nim")
cpFile("nim-glib/src/glib.nim", td / wd / "glib.nim")
cpFile("nim-gobject/src/gobject.nim", td / wd / "gobject.nim")
cpFile("nim-gir/src/gir.nim", td / wd / "gir.nim")
cd(td)
cd(wd)
exec("nim c gen.nim")
mkDir("nim_gi")
exec(td / wd / "gen")
let mods = listFiles("nim_gi")
for i in mods:
let j = i[7 .. ^1]
cpFile(i, this / "gintro" / j)
cd(td)
rmDir(wd) # cleanup
task prepare, "preparing gintro":
#before install:
echo "preparing gintro"
prep()

3706
gintro/atk.nim Normal file

File diff suppressed because it is too large Load diff

80
gintro/cairo.nim Normal file
View file

@ -0,0 +1,80 @@
# dependencies:
# immediate dependencies:
# libraries:
# libcairo-gobject.so.2
{.deadCodeElim: on.}
const Lib* = "libcairo-gobject.so.2"
{.pragma: libprag, cdecl, dynlib: Lib.}
type
Context00* {.pure.} = object
Context* = ref object
impl*: ptr Context00
type
Surface00* {.pure.} = object
Surface* = ref object
impl*: ptr Surface00
type
Matrix00* {.pure.} = object
Matrix* = ref object
impl*: ptr Matrix00
type
Pattern00* {.pure.} = object
Pattern* = ref object
impl*: ptr Pattern00
type
Region00* {.pure.} = object
Region* = ref object
impl*: ptr Region00
type
Content* {.size: sizeof(cint), pure.} = enum
COLOR = 4096
ALPHA = 8192
COLOR_ALPHA = 12288
type
FontOptions00* {.pure.} = object
FontOptions* = ref object
impl*: ptr FontOptions00
type
FontType00* {.pure.} = object
FontType* = ref object
impl*: ptr FontType00
type
FontFace00* {.pure.} = object
FontFace* = ref object
impl*: ptr FontFace00
type
ScaledFont00* {.pure.} = object
ScaledFont* = ref object
impl*: ptr ScaledFont00
type
Path00* {.pure.} = object
Path* = ref object
impl*: ptr Path00
type
RectangleInt00* {.pure.} = object
x*: int32
y*: int32
width*: int32
height*: int32
RectangleInt* = ref object
impl*: ptr RectangleInt00
proc cairo_image_surface_create*() {.
importc: "cairo_image_surface_create", libprag.}
proc imageSurfaceCreate*() {.
importc: "cairo_image_surface_create", libprag.}
# === remaining symbols:

12452
gintro/gdk.nim Normal file

File diff suppressed because it is too large Load diff

1565
gintro/gdkpixbuf.nim Normal file

File diff suppressed because it is too large Load diff

21398
gintro/gio.nim Normal file

File diff suppressed because it is too large Load diff

10450
gintro/glib.nim Normal file

File diff suppressed because it is too large Load diff

75
gintro/gmodule.nim Normal file
View file

@ -0,0 +1,75 @@
# dependencies:
# GLib-2.0
# immediate dependencies:
# GLib-2.0
# libraries:
# libgmodule-2.0.so.0
{.deadCodeElim: on.}
import glib
const Lib* = "libgmodule-2.0.so.0"
{.pragma: libprag, cdecl, dynlib: Lib.}
let Quark = g_quark_from_static_string("NimGIQuark")
type
Module00* {.pure.} = object
Module* = ref object
impl*: ptr Module00
proc g_module_close*(self: ptr Module00): gboolean {.
importc: "g_module_close", libprag.}
proc close*(self: Module): bool =
toBool(g_module_close(cast[ptr Module00](self.impl)))
proc g_module_make_resident*(self: ptr Module00) {.
importc: "g_module_make_resident", libprag.}
proc makeResident*(self: Module) =
g_module_make_resident(cast[ptr Module00](self.impl))
proc g_module_name*(self: ptr Module00): cstring {.
importc: "g_module_name", libprag.}
proc name*(self: Module): string =
let resul0 = g_module_name(cast[ptr Module00](self.impl))
result = $resul0
proc g_module_symbol*(self: ptr Module00; symbolName: cstring; symbol: var pointer): gboolean {.
importc: "g_module_symbol", libprag.}
proc symbol*(self: Module; symbolName: string; symbol: var pointer): bool =
toBool(g_module_symbol(cast[ptr Module00](self.impl), cstring(symbolName), symbol))
proc g_module_build_path*(directory: cstring; moduleName: cstring): cstring {.
importc: "g_module_build_path", libprag.}
proc buildPath*(directory: string; moduleName: string): string =
let resul0 = g_module_build_path(cstring(directory), cstring(moduleName))
result = $resul0
cogfree(resul0)
proc g_module_error*(): cstring {.
importc: "g_module_error", libprag.}
proc error*(): string =
let resul0 = g_module_error()
result = $resul0
proc g_module_supported*(): gboolean {.
importc: "g_module_supported", libprag.}
proc supported*(): gboolean {.
importc: "g_module_supported", libprag.}
type
ModuleCheckInit* = proc (module: ptr Module00): cstring {.cdecl.}
type
ModuleFlags* {.size: sizeof(cint), pure.} = enum
lazy = 1
local = 2
mask = 3
type
ModuleUnload* = proc (module: ptr Module00) {.cdecl.}
# === remaining symbols:

2162
gintro/gobject.nim Normal file

File diff suppressed because it is too large Load diff

50546
gintro/gtk.nim Normal file

File diff suppressed because it is too large Load diff

3884
gintro/pango.nim Normal file

File diff suppressed because it is too large Load diff

428
gintro/rsvg.nim Normal file
View file

@ -0,0 +1,428 @@
# dependencies:
# cairo-1.0
# GLib-2.0
# Gio-2.0
# GObject-2.0
# GModule-2.0
# GdkPixbuf-2.0
# immediate dependencies:
# cairo-1.0
# Gio-2.0
# GdkPixbuf-2.0
# GObject-2.0
# GLib-2.0
# libraries:
# librsvg-2.so.2
{.deadCodeElim: on.}
import cairo, glib, gio, gobject, gmodule, gdkpixbuf
const Lib* = "librsvg-2.so.2"
{.pragma: libprag, cdecl, dynlib: Lib.}
let Quark = g_quark_from_static_string("NimGIQuark")
type
DimensionData00* {.pure.} = object
width*: int32
height*: int32
em*: cdouble
ex*: cdouble
DimensionData* = ref object
impl*: ptr DimensionData00
type
Error* {.size: sizeof(cint), pure.} = enum
errorFailed = 0
type
HandlePrivate00* {.pure.} = object
HandlePrivate* = ref object
impl*: ptr HandlePrivate00
type
Handle* = ref object of gobject.Object
Handle00* = object of gobject.Object00
priv1: ptr HandlePrivate00
abiPadding*: array[15, pointer]
proc rsvg_handle_new*(): ptr Handle00 {.
importc: "rsvg_handle_new", libprag.}
proc newHandle*(): Handle =
new(result, finalizeGObject)
result.impl = rsvg_handle_new()
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc initHandle*[T](result: var T) =
assert(result is Handle)
new(result, finalizeGObject)
result.impl = rsvg_handle_new()
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc rsvg_handle_new_from_data*(data: uint8Array; dataLen: uint64): ptr Handle00 {.
importc: "rsvg_handle_new_from_data", libprag.}
proc newHandleFromData*(data: uint8Array; dataLen: uint64): Handle =
new(result, finalizeGObject)
result.impl = rsvg_handle_new_from_data(data, dataLen)
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc initHandleFromData*[T](result: var T; data: uint8Array; dataLen: uint64) =
assert(result is Handle)
new(result, finalizeGObject)
result.impl = rsvg_handle_new_from_data(data, dataLen)
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc rsvg_handle_new_from_file*(fileName: cstring): ptr Handle00 {.
importc: "rsvg_handle_new_from_file", libprag.}
proc newHandleFromFile*(fileName: string): Handle =
new(result, finalizeGObject)
result.impl = rsvg_handle_new_from_file(cstring(fileName))
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc initHandleFromFile*[T](result: var T; fileName: string) =
assert(result is Handle)
new(result, finalizeGObject)
result.impl = rsvg_handle_new_from_file(cstring(fileName))
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc rsvg_handle_close*(self: ptr Handle00): gboolean {.
importc: "rsvg_handle_close", libprag.}
proc close*(self: Handle): bool =
toBool(rsvg_handle_close(cast[ptr Handle00](self.impl)))
proc rsvg_handle_get_base_uri*(self: ptr Handle00): cstring {.
importc: "rsvg_handle_get_base_uri", libprag.}
proc getBaseUri*(self: Handle): string =
let resul0 = rsvg_handle_get_base_uri(cast[ptr Handle00](self.impl))
result = $resul0
proc baseUri*(self: Handle): string =
let resul0 = rsvg_handle_get_base_uri(cast[ptr Handle00](self.impl))
result = $resul0
proc rsvg_handle_get_dimensions*(self: ptr Handle00; dimensionData: var DimensionData00) {.
importc: "rsvg_handle_get_dimensions", libprag.}
proc getDimensions*(self: ptr Handle00; dimensionData: var DimensionData00) {.
importc: "rsvg_handle_get_dimensions", libprag.}
proc dimensions*(self: ptr Handle00; dimensionData: var DimensionData00) {.
importc: "rsvg_handle_get_dimensions", libprag.}
proc rsvg_handle_get_dimensions_sub*(self: ptr Handle00; dimensionData: var DimensionData00;
id: cstring): gboolean {.
importc: "rsvg_handle_get_dimensions_sub", libprag.}
proc getDimensionsSub*(self: ptr Handle00; dimensionData: var DimensionData00;
id: cstring): gboolean {.
importc: "rsvg_handle_get_dimensions_sub", libprag.}
proc dimensionsSub*(self: ptr Handle00; dimensionData: var DimensionData00;
id: cstring): gboolean {.
importc: "rsvg_handle_get_dimensions_sub", libprag.}
proc rsvg_handle_get_pixbuf*(self: ptr Handle00): ptr gdkpixbuf.Pixbuf00 {.
importc: "rsvg_handle_get_pixbuf", libprag.}
proc getPixbuf*(self: Handle): gdkpixbuf.Pixbuf =
let gobj = rsvg_handle_get_pixbuf(cast[ptr Handle00](self.impl))
if g_object_get_qdata(gobj, Quark) != nil:
result = cast[gdkpixbuf.Pixbuf](g_object_get_qdata(gobj, Quark))
assert(result.impl == gobj)
else:
new(result, finalizeGObject)
result.impl = gobj
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc pixbuf*(self: Handle): gdkpixbuf.Pixbuf =
let gobj = rsvg_handle_get_pixbuf(cast[ptr Handle00](self.impl))
if g_object_get_qdata(gobj, Quark) != nil:
result = cast[gdkpixbuf.Pixbuf](g_object_get_qdata(gobj, Quark))
assert(result.impl == gobj)
else:
new(result, finalizeGObject)
result.impl = gobj
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc rsvg_handle_get_pixbuf_sub*(self: ptr Handle00; id: cstring): ptr gdkpixbuf.Pixbuf00 {.
importc: "rsvg_handle_get_pixbuf_sub", libprag.}
proc getPixbufSub*(self: Handle; id: string): gdkpixbuf.Pixbuf =
let gobj = rsvg_handle_get_pixbuf_sub(cast[ptr Handle00](self.impl), cstring(id))
if g_object_get_qdata(gobj, Quark) != nil:
result = cast[gdkpixbuf.Pixbuf](g_object_get_qdata(gobj, Quark))
assert(result.impl == gobj)
else:
new(result, finalizeGObject)
result.impl = gobj
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc pixbufSub*(self: Handle; id: string): gdkpixbuf.Pixbuf =
let gobj = rsvg_handle_get_pixbuf_sub(cast[ptr Handle00](self.impl), cstring(id))
if g_object_get_qdata(gobj, Quark) != nil:
result = cast[gdkpixbuf.Pixbuf](g_object_get_qdata(gobj, Quark))
assert(result.impl == gobj)
else:
new(result, finalizeGObject)
result.impl = gobj
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc rsvg_handle_has_sub*(self: ptr Handle00; id: cstring): gboolean {.
importc: "rsvg_handle_has_sub", libprag.}
proc hasSub*(self: Handle; id: string): bool =
toBool(rsvg_handle_has_sub(cast[ptr Handle00](self.impl), cstring(id)))
proc rsvg_handle_read_stream_sync*(self: ptr Handle00; stream: ptr gio.InputStream00;
cancellable: ptr gio.Cancellable00): gboolean {.
importc: "rsvg_handle_read_stream_sync", libprag.}
proc readStreamSync*(self: Handle; stream: gio.InputStream; cancellable: gio.Cancellable): bool =
toBool(rsvg_handle_read_stream_sync(cast[ptr Handle00](self.impl), cast[ptr gio.InputStream00](stream.impl), cast[ptr gio.Cancellable00](cancellable.impl)))
proc rsvg_handle_render_cairo*(self: ptr Handle00; cr: ptr cairo.Context00): gboolean {.
importc: "rsvg_handle_render_cairo", libprag.}
proc renderCairo*(self: Handle; cr: cairo.Context): bool =
toBool(rsvg_handle_render_cairo(cast[ptr Handle00](self.impl), cast[ptr cairo.Context00](cr.impl)))
proc rsvg_handle_render_cairo_sub*(self: ptr Handle00; cr: ptr cairo.Context00; id: cstring): gboolean {.
importc: "rsvg_handle_render_cairo_sub", libprag.}
proc renderCairoSub*(self: Handle; cr: cairo.Context; id: string): bool =
toBool(rsvg_handle_render_cairo_sub(cast[ptr Handle00](self.impl), cast[ptr cairo.Context00](cr.impl), cstring(id)))
proc rsvg_handle_set_base_gfile*(self: ptr Handle00; baseFile: ptr gio.File00) {.
importc: "rsvg_handle_set_base_gfile", libprag.}
proc setBaseGfile*(self: Handle; baseFile: gio.File) =
rsvg_handle_set_base_gfile(cast[ptr Handle00](self.impl), cast[ptr gio.File00](baseFile.impl))
proc `baseGfile=`*(self: Handle; baseFile: gio.File) =
rsvg_handle_set_base_gfile(cast[ptr Handle00](self.impl), cast[ptr gio.File00](baseFile.impl))
proc rsvg_handle_set_base_uri*(self: ptr Handle00; baseUri: cstring) {.
importc: "rsvg_handle_set_base_uri", libprag.}
proc setBaseUri*(self: Handle; baseUri: string) =
rsvg_handle_set_base_uri(cast[ptr Handle00](self.impl), cstring(baseUri))
proc `baseUri=`*(self: Handle; baseUri: string) =
rsvg_handle_set_base_uri(cast[ptr Handle00](self.impl), cstring(baseUri))
proc rsvg_handle_set_dpi*(self: ptr Handle00; dpi: cdouble) {.
importc: "rsvg_handle_set_dpi", libprag.}
proc setDpi*(self: Handle; dpi: cdouble) =
rsvg_handle_set_dpi(cast[ptr Handle00](self.impl), dpi)
proc `dpi=`*(self: Handle; dpi: cdouble) =
rsvg_handle_set_dpi(cast[ptr Handle00](self.impl), dpi)
proc rsvg_handle_set_dpi_x_y*(self: ptr Handle00; dpiX: cdouble; dpiY: cdouble) {.
importc: "rsvg_handle_set_dpi_x_y", libprag.}
proc setDpiXY*(self: Handle; dpiX: cdouble; dpiY: cdouble) =
rsvg_handle_set_dpi_x_y(cast[ptr Handle00](self.impl), dpiX, dpiY)
proc rsvg_handle_write*(self: ptr Handle00; buf: uint8Array; count: uint64): gboolean {.
importc: "rsvg_handle_write", libprag.}
proc write*(self: Handle; buf: uint8Array; count: uint64): bool =
toBool(rsvg_handle_write(cast[ptr Handle00](self.impl), buf, count))
type
HandleFlag* {.size: sizeof(cint), pure.} = enum
flagUnlimited = 1
flagKeepImageData = 2
HandleFlags* {.size: sizeof(cint).} = set[HandleFlag]
proc rsvg_handle_new_from_gfile_sync*(file: ptr gio.File00; flags: HandleFlags; cancellable: ptr gio.Cancellable00): ptr Handle00 {.
importc: "rsvg_handle_new_from_gfile_sync", libprag.}
proc newHandleFromGfileSync*(file: gio.File; flags: HandleFlags; cancellable: gio.Cancellable): Handle =
new(result, finalizeGObject)
result.impl = rsvg_handle_new_from_gfile_sync(cast[ptr gio.File00](file.impl), flags, cast[ptr gio.Cancellable00](cancellable.impl))
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc initHandleFromGfileSync*[T](result: var T; file: gio.File; flags: HandleFlags; cancellable: gio.Cancellable) =
assert(result is Handle)
new(result, finalizeGObject)
result.impl = rsvg_handle_new_from_gfile_sync(cast[ptr gio.File00](file.impl), flags, cast[ptr gio.Cancellable00](cancellable.impl))
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc rsvg_handle_new_from_stream_sync*(inputStream: ptr gio.InputStream00; baseFile: ptr gio.File00;
flags: HandleFlags; cancellable: ptr gio.Cancellable00): ptr Handle00 {.
importc: "rsvg_handle_new_from_stream_sync", libprag.}
proc newHandleFromStreamSync*(inputStream: gio.InputStream; baseFile: gio.File;
flags: HandleFlags; cancellable: gio.Cancellable): Handle =
new(result, finalizeGObject)
result.impl = rsvg_handle_new_from_stream_sync(cast[ptr gio.InputStream00](inputStream.impl), cast[ptr gio.File00](baseFile.impl), flags, cast[ptr gio.Cancellable00](cancellable.impl))
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc initHandleFromStreamSync*[T](result: var T; inputStream: gio.InputStream; baseFile: gio.File;
flags: HandleFlags; cancellable: gio.Cancellable) =
assert(result is Handle)
new(result, finalizeGObject)
result.impl = rsvg_handle_new_from_stream_sync(cast[ptr gio.InputStream00](inputStream.impl), cast[ptr gio.File00](baseFile.impl), flags, cast[ptr gio.Cancellable00](cancellable.impl))
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc rsvg_handle_new_with_flags*(flags: HandleFlags): ptr Handle00 {.
importc: "rsvg_handle_new_with_flags", libprag.}
proc newHandleWithFlags*(flags: HandleFlags): Handle =
new(result, finalizeGObject)
result.impl = rsvg_handle_new_with_flags(flags)
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc initHandleWithFlags*[T](result: var T; flags: HandleFlags) =
assert(result is Handle)
new(result, finalizeGObject)
result.impl = rsvg_handle_new_with_flags(flags)
GC_ref(result)
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
type
PositionData00* {.pure.} = object
x*: int32
y*: int32
PositionData* = ref object
impl*: ptr PositionData00
proc rsvg_handle_get_position_sub*(self: ptr Handle00; positionData: var PositionData00;
id: cstring): gboolean {.
importc: "rsvg_handle_get_position_sub", libprag.}
proc getPositionSub*(self: ptr Handle00; positionData: var PositionData00;
id: cstring): gboolean {.
importc: "rsvg_handle_get_position_sub", libprag.}
proc positionSub*(self: ptr Handle00; positionData: var PositionData00;
id: cstring): gboolean {.
importc: "rsvg_handle_get_position_sub", libprag.}
type
HandleClass00* {.pure.} = object
parent*: gobject.ObjectClass00
abiPadding*: array[15, pointer]
HandleClass* = ref object
impl*: ptr HandleClass00
const MAJOR_VERSION* = 2'i32
const MICRO_VERSION* = 17'i32
const MINOR_VERSION* = 40'i32
const VERSION* = "2.40.17"
proc rsvg_cleanup*() {.
importc: "rsvg_cleanup", libprag.}
proc cleanup*() {.
importc: "rsvg_cleanup", libprag.}
proc rsvg_error_quark*(): uint32 {.
importc: "rsvg_error_quark", libprag.}
proc rsvg_set_default_dpi*(dpi: cdouble) {.
importc: "rsvg_set_default_dpi", libprag.}
proc setDefaultDpi*(dpi: cdouble) {.
importc: "rsvg_set_default_dpi", libprag.}
proc `defaultDpi=`*(dpi: cdouble) {.
importc: "rsvg_set_default_dpi", libprag.}
proc rsvg_set_default_dpi_x_y*(dpiX: cdouble; dpiY: cdouble) {.
importc: "rsvg_set_default_dpi_x_y", libprag.}
proc setDefaultDpiXY*(dpiX: cdouble; dpiY: cdouble) {.
importc: "rsvg_set_default_dpi_x_y", libprag.}
proc `defaultDpiXY=`*(dpiX: cdouble; dpiY: cdouble) {.
importc: "rsvg_set_default_dpi_x_y", libprag.}
# === remaining symbols:

65
gintro/xlib.nim Normal file
View file

@ -0,0 +1,65 @@
# dependencies:
# immediate dependencies:
# libraries:
#
{.deadCodeElim: on.}
const Lib* = ""
{.pragma: libprag, cdecl, dynlib: Lib.}
type
Display00* {.pure.} = object
Display* = ref object
impl*: ptr Display00
type
Screen00* {.pure.} = object
Screen* = ref object
impl*: ptr Screen00
type
Visual00* {.pure.} = object
Visual* = ref object
impl*: ptr Visual00
type
XEvent00* = object {.union.}
XEvent* = ref object
impl*: ptr XEvent00
type
XConfigureEvent00* {.pure.} = object
XConfigureEvent* = ref object
impl*: ptr XConfigureEvent00
type
XImage00* {.pure.} = object
XImage* = ref object
impl*: ptr XImage00
type
XFontStruct00* {.pure.} = object
XFontStruct* = ref object
impl*: ptr XFontStruct00
type
XTrapezoid00* {.pure.} = object
XTrapezoid* = ref object
impl*: ptr XTrapezoid00
type
XVisualInfo00* {.pure.} = object
XVisualInfo* = ref object
impl*: ptr XVisualInfo00
type
XWindowAttributes00* {.pure.} = object
XWindowAttributes* = ref object
impl*: ptr XWindowAttributes00
proc XOpenDisplay*() {.
importc: "XOpenDisplay", libprag.}
proc openDisplay*() {.
importc: "XOpenDisplay", libprag.}
# === remaining symbols:

181
tests/combinatorics.nim Normal file
View file

@ -0,0 +1,181 @@
#
#
# Nimrod Combinatorics Module
# (c) Copyright 2014 Reimer Behrends
#
# See the file "LICENSE", included in this
# distribution, for details about the copyright.
#
## The combinatorics module contains routines to enumerate permutations,
## choices, or combinations of a sequence or array. These routines are
## implemented as iterators that yield sequences. ``sequtils.toSeq``
## can be used to gather all results in a single sequence.
##
## The implementations assume that the input does not contain duplicates;
## if it contains duplicate entries, these will be treated as distinct
## items.
iterator permutations*[T](s: openarray[T]): seq[T] =
## Enumerates all possible permutations of `s`. Example:
##
## .. code-block:: nimrod
## for p in permutations(@[1,2,3]):
##
## ...generates this output:
##
## .. code-block::
## @[1, 2, 3]
## @[2, 1, 3]
## @[1, 3, 2]
## @[2, 3, 1]
## @[3, 2, 1]
## @[3, 1, 2]
let n = len(s)
var pos = newSeq[int](n)
var current = newSeq[T](n)
for i in 0..n-1:
pos[i] = i
while true:
for i in 0..n-1:
current[i] = current[pos[i]]
current[pos[i]] = s[i]
yield current
var i = 1
while i < n:
pos[i] -= 1
if pos[i] < 0:
pos[i] = i
i += 1
else:
break
if i >= n:
break
iterator combinations*[T](s: openarray[T], k: int): seq[T] =
## Enumerates all combinations of `k` distinct elements
## out of `s`. Example:
##
## .. code-block:: nimrod
## for p in combinations(@[1,2,3], 2):
##
## ...generates this output:
##
## .. code-block::
## @[1, 2]
## @[1, 3]
## @[2, 3]
let n = len(s)
assert k >= 0 and k <= n
var pos = newSeq[int](k)
var current = newSeq[T](k)
for i in 0..k-1:
pos[k-i-1] = i
var done = false
while not done:
for i in 0..k-1:
current[i] = s[pos[k-i-1]]
yield current
var i = 0
while i < k:
pos[i] += 1
if pos[i] < n-i:
for j in 0..i-1:
pos[j] = pos[i] + i - j
break
i += 1
if i >= k:
break
iterator multicombinations*[T](s: openarray[T], k: int): seq[T] =
## Enumerates all ordered combinations of `k` elements
## out of `s` where the elements can be repeated.
## Example:
##
## .. code-block:: nimrod
## for p in multicombinations(@[1,2,3], 2):
##
## ...generates this output:
##
## .. code-block::
## @[1, 1]
## @[1, 2]
## @[1, 3]
## @[2, 2]
## @[2, 3]
## @[3, 3]
let n = len(s)
assert k >= 0 and k <= n
var pos = newSeq[int](k)
var current = newSeq[T](k)
var done = false
while not done:
for i in 0..k-1:
current[i] = s[pos[k-i-1]]
yield current
var i = 0
while i < k:
pos[i] += 1
if pos[i] < n:
for j in 0..i-1:
pos[j] = pos[i]
break
i += 1
if i == k:
break
iterator tuples*[T](s: openarray[T], k: int): seq[T] =
## Enumerates all ordered combinations of `k` elements
## out of `s` where the elements can be repeated. This is
## essentially the Cartesian product of `s` with itself
## for `k` factors. Example:
##
## .. code-block:: nimrod
## for p in tuples(@[1,2], 2):
##
## ...generates this output:
##
## .. code-block::
## @[1, 1]
## @[1, 2]
## @[2, 1]
## @[2, 2]
if k >= 0 and len(s) > 0:
var pos = newSeq[int](k)
var current = newSeq[T](k)
while true:
for i in 0..k-1:
current[i] = s[pos[i]]
yield current
var i = 0
while i < k:
pos[i] += 1
if pos[i] >= len(s):
pos[i] = 0
i += 1
else:
break
if i == k:
break
when isMainModule:
import sets, math, sequtils
template count(s: untyped): untyped =
block:
var i = 0
for x in s: i += 1
i
proc mcoeff(a, b: int): int =
binom(a+b-1, b)
doAssert count(permutations[int]([])) == 1
doAssert count(permutations([1,2,3,4,5])) == fac(5)
doAssert count(permutations(["a", "b", "c"])) == fac(3)
doAssert count(combinations([1,2,3,4], 1)) == binom(4, 1)
doAssert count(combinations([1,2,3,4], 2)) == binom(4, 2)
doAssert count(combinations([1,2,3,4], 3)) == binom(4, 3)
doAssert count(combinations(["a", "b", "c", "d", "e"], 3)) == 10
doAssert count(multicombinations([1,2,3,4], 1)) == mcoeff(4, 1)
doAssert count(multicombinations([1,2,3,4], 2)) == mcoeff(4, 2)
doAssert count(multicombinations([1,2,3,4], 3)) == mcoeff(4, 3)
doAssert count(tuples([1,2,3,4], 3)) == 4*4*4
doAssert count(tuples([1,2], 10)) == 1024

1221
tests/gen.nim Normal file

File diff suppressed because it is too large Load diff