release v0.2

This commit is contained in:
Stefan Salewski 2017-08-30 12:10:19 +02:00
commit 765ecaf9cc
12 changed files with 3048 additions and 78 deletions

View file

@ -1,6 +1,6 @@
= High level GTK3 bindings for the Nim programming language = High level GTK3 bindings for the Nim programming language
(c) Stefan Salewski (c) Stefan Salewski
//Version 0.1 2017 //Version 0.2 2017
:experimental: :experimental:
:imagesdir: http://ssalewski.de/tmp :imagesdir: http://ssalewski.de/tmp
:source-highlighter: pygments :source-highlighter: pygments

View file

@ -1,6 +1,6 @@
# app0.nim -- minimal application style example # app0.nim -- minimal application style example
# nim c app0.nim # nim c app0.nim
import gintro/gtk import gintro/[gtk, glib, gobject]
import gintro/gio except Application, newApplication # we want to use GTK application import gintro/gio except Application, newApplication # we want to use GTK application
#from gintro/gio import ApplicationFlags, scActivate, run #from gintro/gio import ApplicationFlags, scActivate, run

View file

@ -1,5 +1,5 @@
# nim c button.nim # nim c button.nim
import gintro/[gtk, glib] import gintro/[gtk, glib, gobject]
import gintro/gio except Application, newApplication import gintro/gio except Application, newApplication
proc buttonClicked (button: Button) = proc buttonClicked (button: Button) =

View file

@ -1,5 +1,5 @@
# nim c connect_args.nim # nim c connect_args.nim
import gintro/[gtk, glib] import gintro/[gtk, glib, gobject]
import gintro/gio except Application, newApplication import gintro/gio except Application, newApplication
type type

View file

@ -1,5 +1,5 @@
# nim c count_button.nim # nim c count_button.nim
import gintro/[gtk, glib] import gintro/[gtk, glib, gobject]
import gintro/gio except Application, newApplication import gintro/gio except Application, newApplication
type type

View file

@ -1,5 +1,5 @@
# nim c label.nim # nim c label.nim
import gintro/[gtk, glib] import gintro/[gtk, glib, gobject]
import gintro/gio except Application, newApplication import gintro/gio except Application, newApplication
proc activate(app: Application) = proc activate(app: Application) =

View file

@ -1,5 +1,5 @@
# nim c t0.nim # nim c t0.nim
import gintro/gtk import gintro/[gtk, gobject]
proc bye(w: Window) = proc bye(w: Window) =
mainQuit() mainQuit()

View file

@ -1,6 +1,6 @@
# Package # Package
version = "0.1.0" version = "0.2.0"
author = "Stefan Salewski" author = "Stefan Salewski"
description = "High level GObject-Introspection based GTK3 bindings" description = "High level GObject-Introspection based GTK3 bindings"
license = "MIT" license = "MIT"

1465
gintro/cairo.nim Normal file

File diff suppressed because it is too large Load diff

137
gintro/gimpl.nim Normal file
View file

@ -0,0 +1,137 @@
let ct4nt = [
"int32|int",
"uint32|int",
"gboolean|toBool",
"cstring|$"]
proc ct5nt(s: string): string =
for i in ct4nt:
if i.startsWith(s):
return i[s.len + 1 .. ^1]
proc findSignal(name, obj: NimNode): string =
let str = ($name).replace("-", "_") & "|"
for i in SCA:
if i.startsWith(str):
let t = i.split("|", 2)[1]
var n = obj
while true:
if n.kind != nnkBracketExpr: break
var h = $getType(n)[1].toStrLit
if h.endsWith(":ObjectType"):
h.setLen(h.len - 11)
if h == t:
return i
n = getType(n)[1]
n = getType(n)[1]
var ProcID: int
macro mconnect(widget: gobject.Object; signal: string; p: untyped; arg: typed; ignoreArg: bool): typed =
inc(ProcID)
let wt = getType(widget)
#echo "@@@", $(getTypeInst(widget).toStrLit)
let at = getTypeInst(arg)
let wts = ($(wt[1].toStrLit)).replace(":ObjectType")
#echo wts
let ats = $at.toStrLit
let signalName = ($signal).replace("-", "_") # maybe we should just use plain proc names
let procNameCdecl = "connect_for_signal_cdecl_" & signalName & $ProcID
let procName = "connect_for_signal_" & signalName & $ProcID
var sn, wid, num, all, ahl: string
let sci = findSignal(signal, wt)
var r1s = """
proc $1$2 {.cdecl.} =
let h: pointer = g_object_get_qdata(self, Quark)
"""
if sci.isNil:
all = "(self: ptr gobject.Object00; xdata: pointer)"
ahl = "(self: gobject.Object)"
r1s.add(" $3(cast[$4](h)")
if not ignoreArg.boolVal:
r1s.add(", cast[$5](xdata)")
r1s.add(")\n")
else:
(sn, wid, num, ahl, all) = sci.split("|")
#echo ahl, all
var resl: string
if ahl.contains("): "):
resl = all.rsplit("): ", 1)[1]
var resu = " $3(cast[$4](h)"
if all.find(";") > 0:
var largs = all.split("; ")
#if largs.len > 0:
largs.delete(0)
largs[^1] = largs[^1].split(")")[0]
var names, types: array[10, string]
var plainArgs = newSeq[string]()
for i in 0 .. largs.high:
if largs[i].endsWith("00"):
(names[i], types[i]) = largs[i].split(": ptr ")
types[i].setLen(types[i].len - 2)
else:
var a1, a2: string
(a1, a2) = largs[i].split(": ")
let h = ct5nt(a2)
if h.len > 0:
a1 = h & "(" & a1 & ")"
plainArgs.add(a1)
#var resu = " $3(cast[$4](h)"
for i in 0 .. 9:
if names[i].isNil: break
resu.add(", " & names[i] & "1")
r1s.add(" var " & names[i] & "1: " & types[i] & "\n")
r1s.add(" new " & names[i] & "1" & "\n")
r1s.add(" " & names[i] & "1.impl = " & names[i] & "\n")
for i in plainArgs:
resu.add(", " & i)
if not ignoreArg.boolVal:
resu.add(", cast[$5](data)")
resu.add(")")
if resl == "gboolean":
resu.add(".ord.gboolean")
r1s.add(resu & "\n")
all = all.replace(")", "; data: pointer)")
r1s = r1s % [$procNameCdecl, all, $p, wts, ats]
#echo r1s
result = parseStmt(r1s)
if not ignoreArg.boolVal:
ahl = ahl.replace(")", "; arg: " & ats & ")")
#echo ahl
if ahl.find(";") > 0:
ahl = "(self: " & wts & ";" & ahl.split(";", 1)[1]
else:
ahl = "(self: " & wts & ")" & ahl.split(")", 1)[1]
#ahl = "(self: " & wts & ")"
let r2s =
if ignoreArg.boolVal:
"""
proc $1(self: $2; p: proc $3) =
sc$4(self, $5, nil)
$1($6, $7)
""" % [$procName, wts, ahl, signalName, $procNameCdecl, $(widget.toStrLit), $p]
else:
"""
proc $1(self: $2; p: proc $3; a: $4) =
when a is RootRef:
GC_ref(a)
sc$5(self, $6, cast[pointer](a))
else:
var ar: ref $4
new(ar)
deepCopy(ar[], a)
GC_ref(ar)
sc$5(self, $6, cast[pointer](ar[]))
$1($7, $8, $9)
""" % [$procName, wts, ahl, ats, signalName, $procNameCdecl, $(widget.toStrLit), $p, $(arg.toStrLit)]
#echo r2s
result.add(parseStmt(r2s))
template connect*(widget: gobject.Object; signal: string; p: untyped; arg: typed): typed =
mconnect(widget, signal, p, arg, false)
template connect*(widget: gobject.Object; signal: string; p: untyped): typed =
mconnect(widget, signal, p, "", true)

View file

@ -1,5 +1,5 @@
# High level gobject-introspection based GTK3 bindings for the Nim programming language # High level gobject-introspection based GTK3 bindings for the Nim programming language
# v 0.1 2017-JUL-21 # v 0.2 2017-AUG-29
# (c) S. Salewski 2017 # (c) S. Salewski 2017
# https://wiki.gnome.org/Projects/GObjectIntrospection # https://wiki.gnome.org/Projects/GObjectIntrospection
@ -69,7 +69,7 @@ type using var when while with without xor yield
""" """
let nims = """ let nims = """
int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float float32 float64 pointer int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float float32 float64 pointer false true string char bool
""" """
proc mysnakeToCamel(s: cstring): string = proc mysnakeToCamel(s: cstring): string =
@ -108,6 +108,7 @@ var fixedProcNames = newTable[string, string]()
var mangledNames = newTable[string, string]() var mangledNames = newTable[string, string]()
var gdkKeys = newTable[string, seq[string]]() var gdkKeys = newTable[string, seq[string]]()
var allSyms: HashSet[string] var allSyms: HashSet[string]
#var scfilter: HashSet[string]
var provInt = newTable[string, seq[string]]() var provInt = newTable[string, seq[string]]()
var interfaceProvider = newTable[string, seq[string]]() var interfaceProvider = newTable[string, seq[string]]()
var priList: seq[string] var priList: seq[string]
@ -124,6 +125,12 @@ var classList: seq[GIBaseInfo]
var ct: CountTable[string] var ct: CountTable[string]
fixedProcNames.add("gtk_button_new_with_label", "newButton") fixedProcNames.add("gtk_button_new_with_label", "newButton")
fixedProcNames.add("pango_font_description_from_string", "newFontDescription")
fixedProcNames.add("pango_language_from_string", "languageFromString")
fixedProcNames.add("gdk_event_get", "getEvent")
fixedProcNames.add("gdk_display_manager_get", "getDisplayManager")
fixedProcNames.add("gdk_display_get_default", "getDefaultDisplay")
defaultParameters.add("gtk_window_new", "`type` WindowType WindowType.toplevel") defaultParameters.add("gtk_window_new", "`type` WindowType WindowType.toplevel")
defaultParameters.add("gtk_application_new", "flags gio.ApplicationFlags {}") defaultParameters.add("gtk_application_new", "flags gio.ApplicationFlags {}")
for i in keywords.split: mangledNames.add(i, '`' & i & '`') for i in keywords.split: mangledNames.add(i, '`' & i & '`')
@ -224,6 +231,7 @@ proc mangleType(s: cstring): string =
echo "!!!", result echo "!!!", result
var output: StringStream var output: StringStream
var supmod: StringStream
var methodBuffer: StringStream var methodBuffer: StringStream
proc genP(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): (string, string, TableRef[string, string]) proc genP(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): (string, string, TableRef[string, string])
@ -264,6 +272,7 @@ proc genRec(t: GITypeInfo; genProxy = false; fullQualified: bool = false): strin
else: else:
var ns = ($gBaseInfoGetNamespace(iface)).toLowerAscii var ns = ($gBaseInfoGetNamespace(iface)).toLowerAscii
result = mangleName($gBaseInfoGetName(iface)) result = mangleName($gBaseInfoGetName(iface))
if ns == "cairo" and moduleNamespace == "pangocairo" and result == "FontType": return result # GI bug?
if gBaseInfoGetType(iface) == GIInfoType.Object or gBaseInfoGetType(iface) == GIInfoType.STRUCT or gBaseInfoGetType(iface) == GIInfoType.UNION or gBaseInfoGetType(iface) == GIInfoType.INTERFACE: if gBaseInfoGetType(iface) == GIInfoType.Object or gBaseInfoGetType(iface) == GIInfoType.STRUCT or gBaseInfoGetType(iface) == GIInfoType.UNION or gBaseInfoGetType(iface) == GIInfoType.INTERFACE:
proxyResult = genProxy proxyResult = genProxy
if not (genProxy or callerAlloc.contains(ns & '.' & result)): if not (genProxy or callerAlloc.contains(ns & '.' & result)):
@ -284,6 +293,7 @@ proc isProxyCandidate(t: GITypeInfo): bool =
let iface = gTypeInfoGetInterface(t) let iface = gTypeInfoGetInterface(t)
var ns = ($gBaseInfoGetNamespace(iface)).toLowerAscii var ns = ($gBaseInfoGetNamespace(iface)).toLowerAscii
if callerAlloc.contains(ns & '.' & $gBaseInfoGetName(iface)): return false if callerAlloc.contains(ns & '.' & $gBaseInfoGetName(iface)): return false
if ns == "cairo" and moduleNamespace == "pangocairo" and $gBaseInfoGetName(iface) == "FontType": return false # GI bug?
result = gBaseInfoGetType(iface) in {GIInfoType.Object, GIInfoType.STRUCT, GIInfoType.UNION, GIInfoType.INTERFACE} result = gBaseInfoGetType(iface) in {GIInfoType.Object, GIInfoType.STRUCT, GIInfoType.UNION, GIInfoType.INTERFACE}
proc needProxyProc(info: GICallableInfo): bool = proc needProxyProc(info: GICallableInfo): bool =
@ -350,11 +360,12 @@ proc genP(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): (str
if gArgInfoIsCallerAllocates(arg): if gArgInfoIsCallerAllocates(arg):
callerAllocCollector.incl(genRec(t, true, true)) callerAllocCollector.incl(genRec(t, true, true))
var str = genRec(t, genProxy and not gArgInfoIsCallerAllocates(arg)) var str = genRec(t, genProxy and not gArgInfoIsCallerAllocates(arg))
if isSignalInfo(info) and isProxyCandidate(t) and not genProxy:
str.insert("ptr ")
var userAlloc: bool var userAlloc: bool
if callerAlloc.contains(genRec(t, true, true)): if callerAlloc.contains(genRec(t, true, true)):
userAlloc = true userAlloc = true
str = genRec(t, true) str = genRec(t, true)
if genProxy: if genProxy:
let tag = gTypeInfoGetTag(t) let tag = gTypeInfoGetTag(t)
if tag == GITypeTag.INTERFACE: if tag == GITypeTag.INTERFACE:
@ -364,7 +375,6 @@ proc genP(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): (str
let provider = interfaceProvider[str] let provider = interfaceProvider[str]
for i in provider: discard mangleType(i) for i in provider: discard mangleType(i)
str = str & " | " & provider.join(" | ") str = str & " | " & provider.join(" | ")
let name = mangleName(gBaseInfoGetName(arg)) let name = mangleName(gBaseInfoGetName(arg))
if isProxyCandidate(t) and not gArgInfoIsCallerAllocates(arg) and not userAlloc: if isProxyCandidate(t) and not gArgInfoIsCallerAllocates(arg) and not userAlloc:
arglist.add("cast[" & genRec(t, false) & "](" & name & ".impl)") arglist.add("cast[" & genRec(t, false) & "](" & name & ".impl)")
@ -425,7 +435,6 @@ proc genP(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): (str
proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) = proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
assert(isCallableInfo(mInfo)) assert(isCallableInfo(mInfo))
assert(isFunctionInfo(mInfo)) assert(isFunctionInfo(mInfo))
var plist, arglist: string var plist, arglist: string
var replist: TableRef[string, string] var replist: TableRef[string, string]
let p = methodBuffer.getPosition let p = methodBuffer.getPosition
@ -453,8 +462,10 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
var asym = manglename(gBaseInfoGetName(mInfo)) var asym = manglename(gBaseInfoGetName(mInfo))
if keywords.split.contains(asym) or nims.split.contains(asym): asym.add('P') if keywords.split.contains(asym) or nims.split.contains(asym): asym.add('P')
var ret2 = gCallableInfoGetReturnType(minfo) var ret2 = gCallableInfoGetReturnType(minfo)
var ret22 = gCallableInfoGetReturnType(minfo)
for run in 0 .. 1: for run in 0 .. 1:
if run == 1: if run == 1:
if fixedProcNames.contains(sym): continue
if not (asym.startsWith("get") or asym.startsWith("set")) or asym == "getPlugin" or asym.len < 4: continue if not (asym.startsWith("get") or asym.startsWith("set")) or asym == "getPlugin" or asym.len < 4: continue
if asym.startsWith("get") and gTypeInfoGetTag(ret2) == GITypeTag.VOID: continue if asym.startsWith("get") and gTypeInfoGetTag(ret2) == GITypeTag.VOID: continue
if asym.startsWith("set"): if asym.startsWith("set"):
@ -478,7 +489,6 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
if gBaseInfoGetType(iface) == GIInfoType.Object: if gBaseInfoGetType(iface) == GIInfoType.Object:
isGObject = true isGObject = true
(plist, arglist, replist) = genP(mInfo, true, info) (plist, arglist, replist) = genP(mInfo, true, info)
if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0: if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0:
if info != nil: if info != nil:
asym = asym.replace("new", "new" & manglename(gBaseInfoGetName(info))) asym = asym.replace("new", "new" & manglename(gBaseInfoGetName(info)))
@ -502,6 +512,7 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
for k, v in replist: for k, v in replist:
let kk = if k[0] == '`': k[1 .. ^2] else: k let kk = if k[0] == '`': k[1 .. ^2] else: k
methodBuffer.writeLine(" var $1_00 = $2($3)" % [kk, v, k]) methodBuffer.writeLine(" var $1_00 = $2($3)" % [kk, v, k])
#[
if isGObject: if isGObject:
methodBuffer.writeLine(" new(result, finalizeGObject)") methodBuffer.writeLine(" new(result, finalizeGObject)")
else: else:
@ -517,9 +528,45 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
methodBuffer.writeLine(" g_object_unref(result.impl)") methodBuffer.writeLine(" g_object_unref(result.impl)")
methodBuffer.writeLine(" assert(g_object_get_qdata(result.impl, Quark) == nil)") methodBuffer.writeLine(" assert(g_object_get_qdata(result.impl, Quark) == nil)")
methodBuffer.writeLine(" g_object_set_qdata(result.impl, Quark, addr(result[]))") methodBuffer.writeLine(" g_object_set_qdata(result.impl, Quark, addr(result[]))")
]#
if isGObject:
# CAUTION: some procs are advertised as constructor but do not construct new objects,
# they just return existing ones as gdk_cursor_new_from_name()
methodBuffer.writeLine(" let gobj = " & sym & arglist)
methodBuffer.writeLine(" if g_object_get_qdata(gobj, Quark) != nil:")
let h = gBaseInfoGetContainer(minfo)
var rt: string
if gBaseInfoGetType(h) == GIInfoType.OBJECT:
rt = mangleType(mangleName(gBaseInfoGetName(h)))
else:
rt = genRec(ret2, true)
#methodBuffer.writeLine(" result = cast[$1](g_object_get_qdata(gobj, Quark))" % [rt])
methodBuffer.writeLine(" result = cast[type(result)](g_object_get_qdata(gobj, Quark))" % [rt])
methodBuffer.writeLine(" assert(result.impl == gobj)")
methodBuffer.writeLine(" else:") # I guess this will never get called...
if sym == "g_object_ref" or sym == "g_object_ref_sink":
methodBuffer.writeLine(" assert(false)")
else:
methodBuffer.writeLine(" new(result, finalizeGObject)")
methodBuffer.writeLine(" result.impl = gobj")
methodBuffer.writeLine(" GC_ref(result)")
methodBuffer.writeLine(" discard g_object_ref_sink(result.impl)")
methodBuffer.writeLine(" g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))")
methodBuffer.writeLine(" g_object_unref(result.impl)")
methodBuffer.writeLine(" assert(g_object_get_qdata(result.impl, Quark) == nil)")
methodBuffer.writeLine(" g_object_set_qdata(result.impl, Quark, addr(result[]))")
else:
methodBuffer.writeLine(" new(result)")
methodBuffer.writeLine(" result.impl = " & sym & arglist)
for k, v in replist:
let kk = if k[0] == '`': k[1 .. ^2] else: k
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, ct3nt(v), kk])
elif isProxyCandidate(ret2): elif isProxyCandidate(ret2):
if info != nil: if info != nil:
asym = asym.replace("new", "new" & manglename(gBaseInfoGetName(info))) asym = asym.replace("new", "new" & manglename(gBaseInfoGetName(info)))
#asym = asym.replace("get", "get" & manglename(gBaseInfoGetName(info)))
if fixedProcNames.contains(sym):
asym = fixedProcNames[sym]
methodBuffer.writeLine("\nproc " & asym & EM & plist & " =") methodBuffer.writeLine("\nproc " & asym & EM & plist & " =")
if gCallableInfoCanThrowGerror(minfo): if gCallableInfoCanThrowGerror(minfo):
methodBuffer.writeLine(" var gerror: ptr Error00") methodBuffer.writeLine(" var gerror: ptr Error00")
@ -580,13 +627,11 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
for k, v in replist: for k, v in replist:
let kk = if k[0] == '`': k[1 .. ^2] else: k let kk = if k[0] == '`': k[1 .. ^2] else: k
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, ct3nt(v), kk]) methodBuffer.writeLine(" $1 = $2($3_00)" % [k, ct3nt(v), kk])
if gCallableInfoCanThrowGerror(minfo): if gCallableInfoCanThrowGerror(minfo):
methodBuffer.writeLine(" if gerror != nil:") methodBuffer.writeLine(" if gerror != nil:")
methodBuffer.writeLine(" let msg = $gerror.message") methodBuffer.writeLine(" let msg = $gerror.message")
methodBuffer.writeLine(" g_error_free(gerror)") methodBuffer.writeLine(" g_error_free(gerror)")
methodBuffer.writeLine(" raise newException(GException, msg)") methodBuffer.writeLine(" raise newException(GException, msg)")
else: else:
(plist, arglist, replist) = genP(mInfo, genProxy, info) (plist, arglist, replist) = genP(mInfo, genProxy, info)
if asym != "errorQuark" and asym != "getPlugin" and asym != "quark": if asym != "errorQuark" and asym != "getPlugin" and asym != "quark":
@ -718,15 +763,7 @@ proc writeEnum(info: GIEnumInfo) =
proc writeObj(info: GIObjectInfo) = proc writeObj(info: GIObjectInfo) =
assert(gBaseInfoGetType(info) == GIInfoType.OBJECT) assert(gBaseInfoGetType(info) == GIInfoType.OBJECT)
let ninterfaces = info.gObjectInfoGetNInterfaces let ninterfaces = info.gObjectInfoGetNInterfaces
#if ninterfaces > 0:
# stdout.write "||| ", gBaseInfoGetName(info), " has ", ninterfaces, " interf: "
# for i in 0 .. < ninterfaces:
# stdout.write " ", gBaseInfoGetName(info.gObjectInfoGetInterface(i)), ","
# stdout.writeLine("")
# stdout.flushFile
let class = gObjectInfoGetClassStruct(info) let class = gObjectInfoGetClassStruct(info)
let n = info.gObjectInfoGetNFields let n = info.gObjectInfoGetNFields
let parent = gObjectInfoGetParent(info) # nil for Object of module gobject! let parent = gObjectInfoGetParent(info) # nil for Object of module gobject!
@ -754,6 +791,14 @@ proc writeObj(info: GIObjectInfo) =
cnt = 9 cnt = 9
if ns == "gio." and gBaseInfoGetName(info) == "NumerableIcon": if ns == "gio." and gBaseInfoGetName(info) == "NumerableIcon":
cnt = 9 cnt = 9
if moduleNamespace == "gtksource" and gBaseInfoGetName(info) == "Buffer":
cnt = 9
if moduleNamespace == "gtksource" and gBaseInfoGetName(info) == "Mark":
cnt = 9
if moduleNamespace == "gtksource" and gBaseInfoGetName(info) == "CompletionInfo":
cnt = 9
if moduleNamespace == "gtksource" and gBaseInfoGetName(info) == "View":
cnt = 9
if not suppressType: if not suppressType:
output.writeLine("type") output.writeLine("type")
if ns == "" and pname != "": # check forward exeption for parent name! if ns == "" and pname != "": # check forward exeption for parent name!
@ -781,7 +826,6 @@ proc writeObj(info: GIObjectInfo) =
continue continue
output.writeLine(" ", name, ": ", h) output.writeLine(" ", name, ": ", h)
if mangleName(gBaseInfoGetName(info)) == "Object" and moduleNamespace == "gobject": if mangleName(gBaseInfoGetName(info)) == "Object" and moduleNamespace == "gobject":
output.writeLine("type") output.writeLine("type")
output.writeLine(" GToggleNotify* = proc (data: pointer; obj: ptr Object00; isLastRef: gboolean) {.cdecl.}\n") output.writeLine(" GToggleNotify* = proc (data: pointer; obj: ptr Object00; isLastRef: gboolean) {.cdecl.}\n")
output.writeLine("proc g_object_add_toggle_ref*(obj: ptr Object00; notify: GToggleNotify; data: pointer) {.") output.writeLine("proc g_object_add_toggle_ref*(obj: ptr Object00; notify: GToggleNotify; data: pointer) {.")
@ -811,14 +855,41 @@ proc writeObj(info: GIObjectInfo) =
if not c.isNil: echo "maybe we should process class closures!" if not c.isNil: echo "maybe we should process class closures!"
if gBaseInfoGetName(signalInfo) == "notify": if gBaseInfoGetName(signalInfo) == "notify":
continue # XXX fix later continue # XXX fix later
var h = genP(signalInfo)[0][1..^1] var h = genP(signalInfo, false)[0][1..^1]
let zzzu = gCallableInfoGetReturnType(signalinfo)
if gCallableInfoGetNArgs(signalInfo) > 0 or gTypeInfoGetTag(zzzu) != GITypeTag.VOID:
var memo = ""
memo.add(gCallableInfoGetNArgs(signalInfo))
memo.add('|')
var plist, arglist: string
var replist: TableRef[string, string]
(plist, arglist, replist) = genP(signalInfo, true, info)
memo.add(plist)
memo.add('|')
(plist, arglist, replist) = genP(signalInfo, false, info)
memo.add(plist)
memo = memo.replace("\n ", "")
supmod.writeLine(" \"" & ($gBaseInfoGetName(signalInfo)).replace("-", "_") & "|" & $gBaseInfoGetName(info) & "|" & memo & "\",")
if gCallableInfoGetNArgs(signalInfo) > 0: if gCallableInfoGetNArgs(signalInfo) > 0:
var plist, arglist: string
var replist: TableRef[string, string]
(plist, arglist, replist) = genP(signalInfo, false, nil)
echo plist
echo arglist
if replist.len > 0:
for k, v in replist:
stdout.write(k & "--" & v & " ")
stdout.writeLine("")
echo "PPP ", gBaseInfoGetName(signalInfo), gCallableInfoGetNArgs(signalInfo)
h = h.replace(")", "; xdata: pointer)") h = h.replace(")", "; xdata: pointer)")
else: else:
h = h.replace(")", "xdata: pointer)") h = h.replace(")", "xdata: pointer)")
var xxx = mangleName(gBaseInfoGetName(info)) var xxx = mangleName(gBaseInfoGetName(info))
output.write("proc " & mangleName("sc_" & $gBaseInfoGetName(signalInfo)) & EM & "(self: " & xxx & "; ") output.write("proc " & mangleName("sc_" & $gBaseInfoGetName(signalInfo)) & EM & "(self: " & xxx & "; ")
output.writeLine(" p: proc (self: ptr gobject.Object00; " & h & " {.cdecl.}, xdata: pointer = nil) =") if gCallableInfoGetNArgs(signalInfo) > 0 or gTypeInfoGetTag(zzzu) != GITypeTag.VOID:
output.writeLine(" p: proc (self: ptr " & xxx & "00; " & h & " {.cdecl.}, xdata: pointer = nil) =")
else:
output.writeLine(" p: proc (self: ptr gobject.Object00; " & h & " {.cdecl.}, xdata: pointer = nil) =")
output.write(" discard g_signal_connect_data(self.impl, \"") output.write(" discard g_signal_connect_data(self.impl, \"")
output.write($gBaseInfoGetName(signalInfo)) output.write($gBaseInfoGetName(signalInfo))
output.writeLine("\", cast[GCallback](p), xdata, nil, cast[ConnectFlags](0))") output.writeLine("\", cast[GCallback](p), xdata, nil, cast[ConnectFlags](0))")
@ -924,10 +995,31 @@ proc processInfo(i: GIBaseInfo) =
writeConst(i) writeConst(i)
else: assert(false) else: assert(false)
const GDK_EPI = """
proc gdk_window_invalidate_nilrect(self: ptr Window00; rect: ptr Rectangle; invalidateChildren: gboolean) {.
importc: "gdk_window_invalidate_rect", libprag.}
proc invalidateRect*(self: Window; rect: ptr Rectangle = nil; invalidateChildren: bool = false) =
gdk_window_invalidate_nilrect(cast[ptr Window00](self.impl), rect, gboolean(invalidateChildren))
proc fixednewCursorFromName*(display: Display; name: string): Cursor =
new(result, finalizeGObject)
result.impl = gdk_cursor_new_from_name(cast[ptr Display00](display.impl), cstring(name))
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[]))
"""
const GIO_EPI = """ const GIO_EPI = """
proc run*(self: Application): int = proc run*(self: Application): int =
int(g_application_run(cast[ptr Application00](self.impl), 0, nil)) int(g_application_run(cast[ptr Application00](self.impl), 0, nil))
""" """
const GTK_EPI = """ const GTK_EPI = """
@ -942,56 +1034,11 @@ proc loadFromData*(self: CssProvider; data: cstring): bool =
import macros, strutils import macros, strutils
var ProcID: int include gisup
include gimpl
macro mconnect(widget: gobject.Object; signal: string; p: untyped; arg: typed; widgett: typedesc; argt: typedesc): typed =
inc(ProcID)
let wt = getType(widgett)[1] # widget type
let at = getType(argt)[1] # argument type
let signalName = ($signal).replace("-", "_") # maybe we should just use plain proc names
let procNameCdecl = newIdentNode("connect_for_signal_cdecl_" & signalName & $ProcID)
let procName = newIdentNode("connect_for_signal_" & signalName & $ProcID)
let scName = newIdentNode("sc" & signalName)
result = quote do:
proc `procNameCdecl`(w: ptr gobject.Object00 , data: pointer) {.cdecl.} =
var h: pointer = g_object_get_qdata(w, Quark)
`p`(cast[`wt`](h), cast[`at`](data))
proc `procName`(self: `wt`; p: proc (self: `wt`, arg: `at`); a: `at`) =
when a is RootRef:
GC_ref(a)
`scName`(self, `procNameCdecl`, cast[pointer](a))
else:
var ar: ref `at`
new(ar)
deepCopy(ar[], a)
GC_ref(ar)
`scName`(self, `procNameCdecl`, cast[pointer](ar[]))
`procName`(`widget`, `p`, `arg`)
template connect*(widget: gobject.Object; signal: string; p: untyped; arg: typed) =
mconnect(widget, signal, p, arg, type(widget), type(arg))
macro mconnect(widget: gobject.Object; signal: string; p: untyped; widgett: typedesc): typed =
inc(ProcID)
let wt = getType(widgett)[1]
let signalName = ($signal).replace("-", "_")
let procNameCdecl = newIdentNode("connect_for_signal_cdecl_" & signalName & $ProcID)
let procName = newIdentNode("connect_for_signal_" & signalName & $ProcID)
let scName = newIdentNode("sc" & signalName)
result = quote do:
proc `procNameCdecl`(w: ptr gobject.Object00 , data: pointer) {.cdecl.} =
var h: pointer = g_object_get_qdata(w, Quark)
`p`(cast[`wt`](h))
proc `procName`(self: `wt`; p: proc (self: `wt`)) =
`scName`(self, `procNameCdecl`, nil)
`procName`(`widget`, `p`)
template connect*(widget: gobject.Object; signal: string; p: untyped) =
mconnect(widget, signal, p, type(widget))
""" """
proc main(namespace: string) = proc main(namespace: string) =
priList = newSeq[string]() priList = newSeq[string]()
suppressType = false suppressType = false
@ -1038,7 +1085,8 @@ proc main(namespace: string) =
output.writeLine("# ", libs) output.writeLine("# ", libs)
output.writeLine("{.deadCodeElim: on.}") output.writeLine("{.deadCodeElim: on.}")
output.writeLine(importedModules) output.writeLine(importedModules)
let Lib = if libs.isNil: "" else: ($libs).split(',', 2)[0] var Lib = if libs.isNil: "" else: ($libs).split(',', 2)[0]
if namespace == "PangoCairo" and Lib.startsWith("libpango-"): Lib = Lib.replace("libpango-", "libpangocairo-") # GI bug?
output.writeLine("const Lib* = \"$1\"" % Lib) output.writeLine("const Lib* = \"$1\"" % Lib)
output.writeLine("{.pragma: libprag, cdecl, dynlib: Lib.}") output.writeLine("{.pragma: libprag, cdecl, dynlib: Lib.}")
if namespace == "GObject": # declare array types to make it compile -- procs using these will need special care! if namespace == "GObject": # declare array types to make it compile -- procs using these will need special care!
@ -1121,7 +1169,8 @@ proc main(namespace: string) =
output.writeLine("type\n File00Array* = pointer") output.writeLine("type\n File00Array* = pointer")
output.writeLine("type\n Array* = pointer") output.writeLine("type\n Array* = pointer")
output.writeLine("type\n OutputVector00Array* = pointer") output.writeLine("type\n OutputVector00Array* = pointer")
elif namespace == "GtkSource":
output.writeLine("import glib")
if namespace == "GObject": if namespace == "GObject":
output.writeLine("\nimport times") output.writeLine("\nimport times")
output.writeLine("var qt = \"NGIQ\" & $epochTime()") output.writeLine("var qt = \"NGIQ\" & $epochTime()")
@ -1207,6 +1256,7 @@ proc main(namespace: string) =
unp.setLen(0) unp.setLen(0)
for k in delayedSyms: for k in delayedSyms:
var pos = output.getPosition var pos = output.getPosition
var supmodpos = supmod.getPosition
try: try:
knownSyms.incl(mangleName(gBaseInfoGetName(k))) knownSyms.incl(mangleName(gBaseInfoGetName(k)))
methodBuffer = newStringStream() methodBuffer = newStringStream()
@ -1217,6 +1267,7 @@ proc main(namespace: string) =
unp.add(k) unp.add(k)
knownSyms.excl(mangleName(gBaseInfoGetName(k))) knownSyms.excl(mangleName(gBaseInfoGetName(k)))
output.cut(pos) output.cut(pos)
supmod.cut(supmodpos)
delayedSyms = unp delayedSyms = unp
block myb: block myb:
for a in 1 .. 2: # process clustered symbols into one single type section for a in 1 .. 2: # process clustered symbols into one single type section
@ -1226,6 +1277,7 @@ proc main(namespace: string) =
unp = delayedSyms unp = delayedSyms
for t in unp.combinations(a + 1): for t in unp.combinations(a + 1):
var pos = output.getPosition var pos = output.getPosition
var supmodpos = supmod.getPosition
methodBuffer = newStringStream() methodBuffer = newStringStream()
let x = delayedMethods.len let x = delayedMethods.len
try: try:
@ -1248,6 +1300,7 @@ proc main(namespace: string) =
for k in t: for k in t:
knownSyms.excl(mangleName(gBaseInfoGetName(k))) knownSyms.excl(mangleName(gBaseInfoGetName(k)))
output.setPosition(pos) output.setPosition(pos)
supmod.cut(supmodpos)
assert delayedMethods.len >= x assert delayedMethods.len >= x
delayedMethods.setLen(x) delayedMethods.setLen(x)
suppressType = false suppressType = false
@ -1271,6 +1324,9 @@ proc main(namespace: string) =
if namespace == "Gio": if namespace == "Gio":
output.write(GIO_EPI) output.write(GIO_EPI)
if namespace == "Gdk":
output.write(GDK_EPI)
output.flush output.flush
var o = open("nim_gi" / (namespace.toLowerAscii) & ".nim", fmWrite) var o = open("nim_gi" / (namespace.toLowerAscii) & ".nim", fmWrite)
o.write(output.data) o.write(output.data)
@ -1281,6 +1337,13 @@ proc main(namespace: string) =
echo gBaseInfoGetName(el[1]) echo gBaseInfoGetName(el[1])
# when isMainModule: # when isMainModule:
#scfilter = initSet[string]()
supmod = newStringStream()
supmod.writeLine("const\n SCA = [")
main("fontconfig")
main("freetype2")
main("PangoCairo")
main("PangoFT2")
main("GLib") main("GLib")
main("GObject") main("GObject")
main("GModule") main("GModule")
@ -1288,10 +1351,18 @@ main("xlib")
main("Gio") main("Gio")
main("Atk") main("Atk")
main("Pango") main("Pango")
main("cairo") # main("cairo") # that file is now hand crafted
main("GdkPixbuf") main("GdkPixbuf")
main("Rsvg") main("Rsvg")
main("Gdk") main("Gdk")
main("Gtk") main("Gtk")
main("GtkSource")
supmod.writeLine(" ]")
supmod.flush
var o = open("nim_gi" / "gisup.nim", fmWrite)
o.write(supmod.data)
o.close()
supmod.close
#for i in callerAllocCollector: echo i #for i in callerAllocCollector: echo i

1297
tests/gen.nim.oldv0.1 Normal file

File diff suppressed because it is too large Load diff