support of optional out proc parameters and some fixes

This commit is contained in:
Stefan Salewski 2020-11-19 09:41:49 +01:00
commit f03791c714
3 changed files with 184 additions and 72 deletions

View file

@ -1,6 +1,6 @@
= High level GTK3 (and GTK4) bindings for the Nim programming language = High level GTK3 (and GTK4) bindings for the Nim programming language
(c) Stefan Salewski (c) Stefan Salewski
//Version 0.8.3 //Version 0.8.4
:experimental: :experimental:
:imagesdir: http://ssalewski.de/tmp :imagesdir: http://ssalewski.de/tmp
:source-highlighter: pygments :source-highlighter: pygments
@ -25,9 +25,13 @@ with code inserted from files directly.
NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf, E. Bassi and other _Nim_ and _GTK/Gnome_ developers. NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf, E. Bassi and other _Nim_ and _GTK/Gnome_ developers.
The `combinatorics` module was kindly provided by R. Behrends. The `combinatorics` module was kindly provided by R. Behrends.
NOTE: This is finally gintro v0.8.3. NOTE: We are currently preparing gintro v0.8.4.
// You may install it with command [black yellow-background]#nimble install gintro@#head#. You may install it with command [black yellow-background]#nimble install gintro@#head#.
This version will have some internal cleanup, which removes the temporary We now try to support optional var out parameters, see https://github.com/StefanSalewski/gintro/issues/102
and tried to fix https://github.com/StefanSalewski/gintro/issues/99. And GtkGestures should work now, thanks
to some hints of Mr. Bassi, see https://discourse.gnome.org/t/gtk4-gtkgesture-and-ref-count/4809.
NOTE: The version gintro v0.8.3 will have some internal cleanup, which removes the temporary
Array types. In the past we used that names to indicate array parameters, it was working well, but still Array types. In the past we used that names to indicate array parameters, it was working well, but still
it was ugly using names to indicates data types. So we fixed that. And we have added some better support for it was ugly using names to indicates data types. So we fixed that. And we have added some better support for
GList parameter. GLists are now converted to Nim seqs and vice versa. Not everywhere still, and this conversion GList parameter. GLists are now converted to Nim seqs and vice versa. Not everywhere still, and this conversion

View file

@ -114,4 +114,84 @@ $1(column, renderer, $6)
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy] """ % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
result = parseStmt(r0s & r1s & r2s) result = parseStmt(r0s & r1s & r2s)
# 117 lines
#[
type
DrawingAreaDrawFunc* = proc (drawingArea: ptr DrawingArea00; cr: ptr cairo.Context00; width: int32;
height: int32; userData: pointer) {.cdecl.}
proc gtk_drawing_area_set_draw_func(self: ptr DrawingArea00; drawFunc: DrawingAreaDrawFunc;
userData: pointer; destroy: DestroyNotify) {.importc, libprag.}
proc setDrawFunc*(self: DrawingArea; drawFunc: DrawingAreaDrawFunc;
userData: pointer; destroy: DestroyNotify) =
gtk_drawing_area_set_draw_func(cast[ptr DrawingArea00](self.impl), drawFunc, userData, destroy)
]#
#
macro msetDrawFunc(da: DrawingArea; p: untyped; arg: typed; ignoreArg: bool): untyped =
var IdleID {.compileTime, global.}: int
inc(IdleID)
let ats = $getTypeInst(arg).toStrLit
let procName = "drawfunc_" & $IdleID
let procNameCdecl = "drawfunc_cdecl_" & $IdleID
var r1s = """
proc $1(self: ptr DrawingArea00; cr: ptr cairo.Context00; width, height: int32; userData: pointer) {.cdecl.} =
let h: pointer = g_object_get_qdata(self, Quark)
var cr1 {.global.}: cairo.Context
if cr1.isNil:
new cr1
GC_ref(cr1) # never call destroy/finalizer on this global variable
cr1.ignoreFinalizer = true
cr1.impl = cr
$2(cast[DrawingArea](h), cr1, width, height"""
if not ignoreArg.boolVal:
if getTypeInst(arg).typeKind == ntyRef:
r1s.add(", cast[$3](userdata)")
else:
#r1s.add(", cast[ptr $3](userdata)[]")
r1s.add(", cast[$3](userdata)")
r1s.add(")\n")
r1s = r1s % [$procNameCdecl, $p, ats]
let r2s =
if ignoreArg.boolVal:
"""
proc $1(self: DrawingArea) =
#gtk_drawing_area_set_draw_func(self.impl, $3, nil, nil)
gtk_drawing_area_set_draw_func(cast[ptr DrawingArea00](self.impl), $3, nil, nil)
$1($5)
""" % [$procName, ats, $procNameCdecl, $(arg.toStrLit), $(da.toStrLit)]
else:
"""
proc $1(self: DrawingArea; a: $2) =
when (a is ref object):
GC_ref(a)
gtk_drawing_area_set_draw_func(self.impl, $3, cast[pointer](a), nil)
else:
var ar: ref $2
new(ar)
#deepCopy(ar[], a)
ar[] = a
GC_ref(ar)
gtk_drawing_area_set_draw_func(cast[ptr DrawingArea00](self.impl), $3, cast[pointer](ar[]), nil)
$1($5, $4)
""" % [$procName, ats, $procNameCdecl, $(arg.toStrLit), $(da.toStrLit)]
echo r1s
echo r2s
result = parseStmt(r1s & r2s)
template setDrawFunc*(da: DrawingArea; p: untyped; arg: typed): untyped =
msetDrawFunc(da, p, arg, false)
template setDrawFunc*(da: DrawingArea; p: untyped): untyped =
msetDrawFunc(da, p, "", true)
# 196 lines

View file

@ -1,6 +1,6 @@
# High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language # High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language
# nimpretty --maxLineLen:130 gen.nim # nimpretty --maxLineLen:130 gen.nim
# v 0.8.4 2020-NOV-02 # v 0.8.4 2020-NOV-18
# (c) S. Salewski 2018 # (c) S. Salewski 2018
# usefull for finding death code: # usefull for finding death code:
@ -277,8 +277,6 @@ proc fixedModName(s: string): string =
result &= "4" result &= "4"
proc gBaseInfoGetName(info: GIBaseInfo): string = proc gBaseInfoGetName(info: GIBaseInfo): string =
#if info == nil:
# return " "
result = $(gir.gBaseInfoGetName(info)) result = $(gir.gBaseInfoGetName(info))
let h = $(gir.gBaseInfoGetNamespace(info)) let h = $(gir.gBaseInfoGetNamespace(info))
if h == "Gio" and result == "Application": if h == "Gio" and result == "Application":
@ -442,6 +440,7 @@ gobject.EnumClass
gtk.RecentData gtk.RecentData
glib.SList glib.SList
glib.List glib.List
nice.Candidate
""" """
const autoCallerAlloc = """ const autoCallerAlloc = """
@ -636,6 +635,7 @@ type
namePlainNS: string namePlainNS: string
name00: string name00: string
flags: RecResFlags flags: RecResFlags
optOut: bool
type type
GPars = tuple GPars = tuple
@ -698,7 +698,6 @@ proc newGenRec(t: GITypeInfo; genProxy = false): RecRes =
if child in UnnamedArrayCandidates: if child in UnnamedArrayCandidates:
result[1] = intA0 # yes we need this # but is wrong, see g_base64_decode result[1] = intA0 # yes we need this # but is wrong, see g_base64_decode
if not gTypeInfoIsZeroTerminated(t): if not gTypeInfoIsZeroTerminated(t):
#echo "bbbbbbbbbb"
result[1] = intAX result[1] = intAX
result.flags.incl(RecResFlag.unamedA) result.flags.incl(RecResFlag.unamedA)
if child in ["TargetEntry00", "PageRange", "KeymapKey"]: if child in ["TargetEntry00", "PageRange", "KeymapKey"]:
@ -717,10 +716,9 @@ proc newGenRec(t: GITypeInfo; genProxy = false): RecRes =
else: else:
result[0] = mangleName($gBaseInfoGetName(iface)) result[0] = mangleName($gBaseInfoGetName(iface))
cAlloc = callerAlloc.contains(ns & '.' & result[0]) cAlloc = callerAlloc.contains(ns & '.' & result[0])
if gBaseInfoGetType(iface) in {GIInfoType.Object, GIInfoType.STRUCT, GIInfoType.UNION, GIInfoType.INTERFACE} and if gBaseInfoGetType(iface) in {GIInfoType.INTERFACE, Object, STRUCT, UNION} and not callerAlloc.contains(ns & '.' & result[0]):
not callerAlloc.contains(ns & '.' & result[0]):
newrawmark = "00" newrawmark = "00"
if gBaseInfoGetType(iface) in {GIInfoType.Object, GIInfoType.STRUCT, GIInfoType.UNION, GIInfoType.INTERFACE}: if gBaseInfoGetType(iface) in {GIInfoType.INTERFACE, Object, STRUCT, UNION}:
proxyResult = genProxy proxyResult = genProxy
if not (genProxy or callerAlloc.contains(ns & '.' & result[0])): if not (genProxy or callerAlloc.contains(ns & '.' & result[0])):
rawmark = "00" rawmark = "00"
@ -748,11 +746,11 @@ proc newGenRec(t: GITypeInfo; genProxy = false): RecRes =
result[0] = mangleType(result[0]) & rawmark result[0] = mangleType(result[0]) & rawmark
proc modPrefix(t: GITypeInfo; sym: string; full = true): string = proc modPrefix(t: GITypeInfo; sym: string; full = true): string =
if sym == "gtk_renderer_cell_accessible_new": if sym in ["gtk_renderer_cell_accessible_new", "gtk_mount_operation_new", "gtk_notebook_page_accessible_new"]:
return fixedModName("gtk") & "." # return fixedModName("gtk") & "."
if sym == "gtk_mount_operation_new": #if sym == "gtk_mount_operation_new":
return fixedModName("gtk") & "." # return fixedModName("gtk") & "."
if sym == "gtk_notebook_page_accessible_new": #if sym == "gtk_notebook_page_accessible_new":
return fixedModName("gtk") & "." return fixedModName("gtk") & "."
if sym in ["gtk_source_view_new", "gtk_source_view_new_with_buffer", "gtk_source_map_new", if sym in ["gtk_source_view_new", "gtk_source_view_new_with_buffer", "gtk_source_map_new",
"gtk_source_style_scheme_chooser_widget_new", "gtk_source_style_scheme_chooser_button_new", "gtk_source_style_scheme_chooser_widget_new", "gtk_source_style_scheme_chooser_button_new",
@ -774,7 +772,7 @@ proc isProxyCandidate(t: GITypeInfo): bool =
let iface = gTypeInfoGetInterface(t) let iface = gTypeInfoGetInterface(t)
let ns = ($gBaseInfoGetNamespace(iface)).toLowerAscii let ns = ($gBaseInfoGetNamespace(iface)).toLowerAscii
if callerAlloc.contains(ns & '.' & $gBaseInfoGetName(iface)): return false if callerAlloc.contains(ns & '.' & $gBaseInfoGetName(iface)): return false
result = gBaseInfoGetType(iface) in {GIInfoType.OBJECT, GIInfoType.STRUCT, GIInfoType.UNION, GIInfoType.INTERFACE} result = gBaseInfoGetType(iface) in {GIInfoType.INTERFACE, OBJECT, STRUCT, UNION}
proc needProxyProc(info: GICallableInfo): bool = proc needProxyProc(info: GICallableInfo): bool =
if gCallableInfoIsMethod(info): if gCallableInfoIsMethod(info):
@ -923,7 +921,7 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil; ge
str = ngr.namePlain str = ngr.namePlain
else: else:
str = ngr.name00 str = ngr.name00
var istr = str #var istr = str
if genProxy and ngr.res == glist: if genProxy and ngr.res == glist:
result.tempRes = " var tempResGL = seq2GList($1)\n" % [mangleName(gBaseInfoGetName(arg))] result.tempRes = " var tempResGL = seq2GList($1)\n" % [mangleName(gBaseInfoGetName(arg))]
if gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING: if gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING:
@ -973,6 +971,9 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil; ge
result.arglist.add("if " & name & ".isNil: nil else: cast[" & ngr.name00 & "](" & name & ".impl)") result.arglist.add("if " & name & ".isNil: nil else: cast[" & ngr.name00 & "](" & name & ".impl)")
else: else:
if gArgInfoGetDirection(arg) == GIDirection.OUT: if gArgInfoGetDirection(arg) == GIDirection.OUT:
if gArgInfoIsOptional(arg):
result.arglist.add("cast[var " & ngr.name00 & "](if addr(" & name & ") == nil: nil else: addr " & name & ".impl)")
else:
result.arglist.add("cast[var " & ngr.name00 & "](addr " & name & ".impl)") result.arglist.add("cast[var " & ngr.name00 & "](addr " & name & ".impl)")
else: else:
result.arglist.add("cast[" & ngr.name00 & "](" & name & ".impl)") result.arglist.add("cast[" & ngr.name00 & "](" & name & ".impl)")
@ -984,8 +985,7 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil; ge
result.arglist.add("cast[" & ngr.name00 & "](unsafeaddr($1[0]))" % name) result.arglist.add("cast[" & ngr.name00 & "](unsafeaddr($1[0]))" % name)
elif (ngr.flags * {RecResFlag.namedA, cstringA} != {}) and gArgInfoGetDirection(arg) == GIDirection.IN: elif (ngr.flags * {RecResFlag.namedA, cstringA} != {}) and gArgInfoGetDirection(arg) == GIDirection.IN:
assert ngr.flags.contains(RecResFlag.array) assert ngr.flags.contains(RecResFlag.array)
result.arglist.add("seq2$1" % [str.replace("00").capitalizeAscii.fixedName] & '(' & name & ", " & StringArrayName & result.arglist.add("seq2$1" % [str.replace("00").capitalizeAscii.fixedName] & '(' & name & ", " & StringArrayName & "$1)" % [num])
"$1)" % [num])
num = "2" num = "2"
elif needTypeConv(str, ngr) and gArgInfoGetDirection(arg) in {GIDirection.OUT, GIDirection.INOUT}: elif needTypeConv(str, ngr) and gArgInfoGetDirection(arg) in {GIDirection.OUT, GIDirection.INOUT}:
result.arglist.add(name.strip(chars = {'`'}) & "_00") result.arglist.add(name.strip(chars = {'`'}) & "_00")
@ -1008,6 +1008,8 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil; ge
if genProxy and needTypeConv(str, ngr): if genProxy and needTypeConv(str, ngr):
if gArgInfoGetDirection(arg) in {GIDirection.OUT, INOUT} and (not gArgInfoIsCallerAllocates(arg) or (str in ["int32", if gArgInfoGetDirection(arg) in {GIDirection.OUT, INOUT} and (not gArgInfoIsCallerAllocates(arg) or (str in ["int32",
"uint32", "ptr cstring", "cstring"])): "uint32", "ptr cstring", "cstring"])):
if gArgInfoGetDirection(arg) in {GIDirection.OUT}:
ngr.optOut = true
result.replist[$name] = (fixedName2($str), ngr) result.replist[$name] = (fixedName2($str), ngr)
if gArgInfoGetDirection(arg) in {GIDirection.OUT, INOUT} or str != "cstring": # new in 0.4.11 -- allow passing cstring if not a var if gArgInfoGetDirection(arg) in {GIDirection.OUT, INOUT} or str != "cstring": # new in 0.4.11 -- allow passing cstring if not a var
str = doTypeConv(str, ngr) str = doTypeConv(str, ngr)
@ -1020,29 +1022,37 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil; ge
if genProxy and defaultParameters.contains(sym): if genProxy and defaultParameters.contains(sym):
for hhh in defaultParameters[sym].split('|'): for hhh in defaultParameters[sym].split('|'):
var h1, h2, h3: string var h1, h2, h3: string
(h1, h2, h3) = hhh.split #defaultParameters[sym].split (h1, h2, h3) = hhh.split
#echo sym, h1," ", h2, " ", h3, " ", str, " ", name
if name == h1 and str == h2: if name == h1 and str == h2:
str.add(" = " & h3) str.add(" = " & h3)
#if sym == "gtk_grid_attach" and name == "height": # as this needs two default parameters if genProxy and (str == "string" or str == "cstring") and mayBeNil and sym != "gtk_check_button_new_with_label":
# str.add(" = " & h3)
if genProxy and (str == "string" or str == "cstring") and mayBeNil:
str.add(" = \"\"") str.add(" = \"\"")
if genProxy and m == 0: if genProxy and m == 0:
if sym.contains("_set_") and str == "bool": if sym.contains("_set_") and str == "bool":
str.add(" = true") str.add(" = true")
if genProxy and isProxyCandidate(t) and mayBeNil: if genProxy and isProxyCandidate(t) and mayBeNil and gArgInfoGetDirection(arg) notin {GIDirection.OUT, INOUT}:
if gArgInfoGetDirection(arg) notin {GIDirection.OUT, GIDirection.INOUT}:
str.add(" = nil") str.add(" = nil")
if (genProxy or sym == "pango_extents_to_pixels") and isFunctionInfo( when false:
info) and ( if genProxy and gArgInfoIsOptional(arg) and gArgInfoGetDirection(arg) == GIDirection.INOUT:
gFunctionInfoGetFlags(info).int and # very few like argc and argv -- we ignore them for now
echo ">>>", sym, " ", mangleName(gBaseInfoGetName(arg))
if genProxy and gArgInfoIsOptional(arg) and gArgInfoGetDirection(arg) in {GIDirection.OUT} and not sym.startsWith("gdk_event_get"):
# https://github.com/nim-lang/Nim/issues/15895
assert(str.startsWith("var "))
var h = str[4 .. ^1]
let l = h.find('|')
if l > 0:
h.setlen(l - 1)
h = h[1 .. ^1]
# str.add(" = cast[ptr $1](nil)[]" % [h])
str.add(" = cast[var $1](nil)" % [h]) # same, see https://forum.nim-lang.org/t/7117
if (genProxy or sym == "pango_extents_to_pixels") and isFunctionInfo(info) and (gFunctionInfoGetFlags(info).int and
GIFunctionInfoFlags.WRAPS_VFUNC.ord) == 0: GIFunctionInfoFlags.WRAPS_VFUNC.ord) == 0:
if userAlloc and mayBeNil: # or (sym == "gdk_window_set_geometry_hints" and str == "Geometry"): # gir bug! if userAlloc and mayBeNil: # or (sym == "gdk_window_set_geometry_hints" and str == "Geometry"): # gir bug!
var h = str var h = str
h.removePrefix("var ") h.removePrefix("var ")
str.add(" = cast[ptr " & h & "](nil)[]") # str.add(" = cast[ptr " & h & "](nil)[]")
str.add(" = cast[var " & h & "](nil)") # the same as above
#if str == "var seq[string]": no var varargs support! #if str == "var seq[string]": no var varargs support!
if str == "seq[string]": if str == "seq[string]":
if j == m: if j == m:
@ -1055,11 +1065,9 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil; ge
if str == "var seq[uint8]": # allow to pass a string for a seq[uint8] argument too if str == "var seq[uint8]": # allow to pass a string for a seq[uint8] argument too
str = "var (seq[uint8] | string)" str = "var (seq[uint8] | string)"
# str = "var (seq[uint8] | openArray[char])" # https://github.com/nim-lang/Nim/issues/15128 # str = "var (seq[uint8] | openArray[char])" # https://github.com/nim-lang/Nim/issues/15128
if genArrayMark and ngr.flags.contains(RecResFlag.array) and str.startsWith("ptr "): if genArrayMark and ngr.flags.contains(RecResFlag.array) and str.startsWith("ptr "):
str.removePrefix("ptr ") str.removePrefix("ptr ")
str.add("Array") str.add("Array")
resus.add((name, str)) resus.add((name, str))
if j < m: if j < m:
result.arglist.add(", ") result.arglist.add(", ")
@ -1089,7 +1097,7 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil; ge
var ngrRet = newGenRec(ret, true) var ngrRet = newGenRec(ret, true)
var r: string var r: string
if genProxy: # and not gArgInfoIsCallerAllocates(arg): if genProxy:
r = ngrRet.namePlain r = ngrRet.namePlain
else: else:
r = ngrRet.name00 r = ngrRet.name00
@ -1113,7 +1121,7 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil; ge
result.arrLex = " let $1 = $2($3.len)\n" % [resus[resusLen][0], h, lastName] result.arrLex = " let $1 = $2($3.len)\n" % [resus[resusLen][0], h, lastName]
resus.delete(resusLen) resus.delete(resusLen)
else: else:
result.arrLex = "" #"#??\n" result.arrLex = ""
result.plist = makePList(resus, self, resusres).isplit(sym.len + "proc".len) result.plist = makePList(resus, self, resusres).isplit(sym.len + "proc".len)
# see also template findFreeProc() # see also template findFreeProc()
@ -1240,7 +1248,6 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
var pars: GPars var pars: GPars
let p = methodBuffer.getPosition let p = methodBuffer.getPosition
#let sym = $gFunctionInfoGetSymbol(mInfo)
let symIsDeprecated = gBaseInfoIsDeprecated(mInfo).int != 0 let symIsDeprecated = gBaseInfoIsDeprecated(mInfo).int != 0
var depStr = "" var depStr = ""
if symIsDeprecated: if symIsDeprecated:
@ -1298,7 +1305,6 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
try: try:
pars = genPars(mInfo, false, info) pars = genPars(mInfo, false, info)
processedFunctions.incl(sym) processedFunctions.incl(sym)
if not sym.startsWith("g_param_spec_uref"): if not sym.startsWith("g_param_spec_uref"):
if sym.startsWith("g_param_spec_", "g_type_interface_", "g_object_interface_"): return if sym.startsWith("g_param_spec_", "g_type_interface_", "g_object_interface_"): return
@ -1367,7 +1373,7 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
if sym in ["g_quark_from_static_string", "g_error_free", "g_object_get_qdata", "g_object_ref_sink", "g_object_unref", if sym in ["g_quark_from_static_string", "g_error_free", "g_object_get_qdata", "g_object_ref_sink", "g_object_unref",
"g_timeout_add_full", "g_object_is_floating", "g_timeout_add_full", "g_object_is_floating",
"g_type_from_name", "g_type_check_instance_is_a", "g_idle_add_full", "g_quark_try_string", "vte_regex_unref", "g_type_from_name", "g_type_check_instance_is_a", "g_idle_add_full", "g_quark_try_string", "vte_regex_unref",
"gtk_builder_get_object"]: "gtk_builder_get_object", "g_action_map_add_action", "gtk_drawing_area_set_draw_func"]:
methodBuffer.write("\nproc " & sym & EM & pars.plist) methodBuffer.write("\nproc " & sym & EM & pars.plist)
methodBuffer.writeLine(" {.\n importc, ", libprag, ".}") methodBuffer.writeLine(" {.\n importc, ", libprag, ".}")
if sym.startsWith("vte_regex_unref"): # this function is special, as it returns the object if sym.startsWith("vte_regex_unref"): # this function is special, as it returns the object
@ -1557,6 +1563,15 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
let arg = gCallableInfoGetArg(minfo, j) let arg = gCallableInfoGetArg(minfo, j)
let t = gArgInfoGetType(arg) let t = gArgInfoGetType(arg)
var ngrt = newGenRec(t) var ngrt = newGenRec(t)
if gArgInfoGetDirection(arg) == GIDirection.IN and gArgInfoGetOwnershipTransfer(arg) == GITransfer.EVERYTHING and
isProxyCandidate(t) and not callerAlloc.contains(ngrt.namePlainNS):
# like gtk_widget_add_controller()
let n = mangleName(gBaseInfoGetName(arg))
if gArgInfoMayBeNull(arg):
methodBuffer.writeLine(" if " & n & " != nil:")
methodBuffer.writeLine(" " & n & ".ignoreFinalizer = true")
else:
methodBuffer.writeLine(" " & n & ".ignoreFinalizer = true")
if gArgInfoGetDirection(arg) == GIDirection.OUT and isProxyCandidate(t) and if gArgInfoGetDirection(arg) == GIDirection.OUT and isProxyCandidate(t) and
not callerAlloc.contains(ngrt.namePlainNS) and not gArgInfoIsCallerAllocates(arg): not callerAlloc.contains(ngrt.namePlainNS) and not gArgInfoIsCallerAllocates(arg):
let tag = gTypeInfoGetTag(t) let tag = gTypeInfoGetTag(t)
@ -1573,6 +1588,16 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
var freeMe: GIFunctionInfo var freeMe: GIFunctionInfo
findFreeProc(info, gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING) findFreeProc(info, gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING)
let h2 = mangleName(gBaseInfoGetName(arg)) let h2 = mangleName(gBaseInfoGetName(arg))
if gArgInfoIsOptional(arg):
#methodBuffer.writeLine(" if cast[ptr $1]($2) != nil:" % [ngrt.namePlain, h2])
methodBuffer.writeLine(" if addr($2) != nil:" % [ngrt.namePlain, h2])
if boxedFreeMeName != "":
methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")")
elif freeMeName == "":
methodBuffer.writeLine(" new(" & h2 & ")")
else:
methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")")
else:
if boxedFreeMeName != "": if boxedFreeMeName != "":
methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")") methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")")
elif freeMeName == "": elif freeMeName == "":
@ -1580,6 +1605,10 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
else: else:
methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")") methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")")
if gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING: if gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING:
if gArgInfoIsOptional(arg):
methodBuffer.writeLine(" if addr($2) != nil:" % [ngrt.namePlain, h2])
methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true")
else:
methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true") # as we have always to attach one with ARC. methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true") # as we have always to attach one with ARC.
if gCallableInfoCanThrowGerror(minfo): if gCallableInfoCanThrowGerror(minfo):
methodBuffer.writeLine(" var gerror: ptr glib.Error") methodBuffer.writeLine(" var gerror: ptr glib.Error")
@ -1591,13 +1620,15 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
#assert not (v[1].flags.contains(RecResFlag.zeroTerminated)) #assert not (v[1].flags.contains(RecResFlag.zeroTerminated))
methodBuffer.writeLine(" var $1x$2: array[$3, pointer]" % [StringArrayName, multi, $StringArrayEntries]) methodBuffer.writeLine(" var $1x$2: array[$3, pointer]" % [StringArrayName, multi, $StringArrayEntries])
methodBuffer.writeLine(" var $1$2: cstringArray = cast[cstringArray](addr $1x$2)" % [StringArrayName, multi]) methodBuffer.writeLine(" var $1$2: cstringArray = cast[cstringArray](addr $1x$2)" % [StringArrayName, multi])
methodBuffer.writeLine(" var $1_00 = seq2$2($3, $4$5)" % [k, v[0].replace("00").capitalizeAscii, k, methodBuffer.writeLine(" var $1_00 = seq2$2($3, $4$5)" % [k, v[0].replace("00").capitalizeAscii, k, StringArrayName, multi])
StringArrayName, multi])
if multi == "": if multi == "":
multi = "1" multi = "1"
elif v[1].flags.contains(RecResFlag.unamedA): elif v[1].flags.contains(RecResFlag.unamedA):
assert v[1].flags.contains(RecResFlag.array) assert v[1].flags.contains(RecResFlag.array)
methodBuffer.writeLine(" var $1_00: $2" % [k, v[1].name00]) methodBuffer.writeLine(" var $1_00: $2" % [k, v[1].name00])
else:
if v[1].optOut:
methodBuffer.writeLine(" var $1_00: $2" % [k.strip(chars = {'`'}), v[0], k])
else: else:
methodBuffer.writeLine(" var $1_00 = $2($3)" % [k.strip(chars = {'`'}), v[0], k]) methodBuffer.writeLine(" var $1_00 = $2($3)" % [k.strip(chars = {'`'}), v[0], k])
if ngrRet.res == glist: if ngrRet.res == glist:
@ -1616,28 +1647,14 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
methodBuffer.writeLine(" result = glistStructs2seq[$1](resul0)" % [ngrRet.childName]) methodBuffer.writeLine(" result = glistStructs2seq[$1](resul0)" % [ngrRet.childName])
if gCallableInfoGetCallerOwns(minfo) != GITransfer.NOTHING: if gCallableInfoGetCallerOwns(minfo) != GITransfer.NOTHING:
methodBuffer.writeLine(" g_list_free(resul0)") methodBuffer.writeLine(" g_list_free(resul0)")
if sym == "g_app_info_get_all":
discard #echo "LLL ", r4
else: else:
if sym == "g_app_info_get_all":
discard #echo "LLL ", r4
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE: if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
if ngrRet.infoType != GIInfoType.INTERFACE: if ngrRet.infoType != GIInfoType.INTERFACE:
assert findFreeObject(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))).len == 0 assert findFreeObject(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))).len == 0
#ignoreFinalizer = gCallableInfoGetCallerOwns(minfo) != GITransfer.EVERYTHING methodBuffer.writeLine(" result = glistObjects2seq($1, $2, $3)" % [ngrRet.childName, sym & pars.arglist, $elTransferFull])
#assert(ignoreFinalizer)
methodBuffer.writeLine(" result = glistObjects2seq($1, $2, $3)" % [ngrRet.childName, sym & pars.arglist,
$elTransferFull])
#echo "FFFFF ", findFreeObject(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0)))
else: else:
if ngrRet.infoType == GIInfoType.STRUCT:
discard ##echo "ffffffff ", findFreeStruct(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0)))
else:
discard #echo "zzz", sym
methodBuffer.writeLine(" discard") methodBuffer.writeLine(" discard")
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER}) assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
#if gCallableInfoGetCallerOwns(minfo) != GITransfer.NOTHING:
# methodBuffer.writeLine(" g_list_free(resul0)")
elif ngrRet.flags.contains(RecResFlag.unamedA) and ngrRet.res == intAX: elif ngrRet.flags.contains(RecResFlag.unamedA) and ngrRet.res == intAX:
# https://discourse.gnome.org/t/g-key-file-get-integer-list-transfer-container/4729 # https://discourse.gnome.org/t/g-key-file-get-integer-list-transfer-container/4729
# for fundamental types GITransfer.EVERYTHING and GITransfer.CONTAINER are equivalent # for fundamental types GITransfer.EVERYTHING and GITransfer.CONTAINER are equivalent
@ -1757,6 +1774,10 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
elif RecResFlag.namedA in v[1].flags: elif RecResFlag.namedA in v[1].flags:
assert v[1].flags.contains(RecResFlag.array) assert v[1].flags.contains(RecResFlag.array)
methodBuffer.writeLine(" $1 = $2($3_00, $4)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'}), pars.blex]) methodBuffer.writeLine(" $1 = $2($3_00, $4)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'}), pars.blex])
else:
if v[1].optOut:
methodBuffer.writeLine(" if $1.addr != nil:" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})])
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})])
else: else:
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})]) methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})])
# BLOCKMARK8 # BLOCKMARK8
@ -2154,7 +2175,7 @@ proc writeModifierType(info: GIEnumInfo) =
output.writeLine(i) output.writeLine(i)
output.writeLine("\n ", we & EM, " {.size: sizeof(cint).} = set[$1Flag]" % [tname]) output.writeLine("\n ", we & EM, " {.size: sizeof(cint).} = set[$1Flag]" % [tname])
if we == "ModifierType": if we == "ModifierType":
output.writeLine("\nconst ModifierMask* = {ModifierFlag.shift .. ModifierFlag.button5, ModifierFlag.super .. ModifierFlag.meta}") #, ModifierFlag.release}") output.writeLine("\nconst ModifierMask* = {ModifierFlag.shift .. ModifierFlag.button5, ModifierFlag.super .. ModifierFlag.meta}")
elif we == "EventMask": elif we == "EventMask":
output.writeLine("\nconst AllEventsMask* = {EventFlag.exposure .. EventFlag.smoothScroll}") output.writeLine("\nconst AllEventsMask* = {EventFlag.exposure .. EventFlag.smoothScroll}")
for j in 0.cint ..< gEnumInfoGetNMethods(info): for j in 0.cint ..< gEnumInfoGetNMethods(info):
@ -2754,6 +2775,9 @@ const GTK_EPI = """
#proc loadFromData*(self: CssProvider; data: cstring): bool = #proc loadFromData*(self: CssProvider; data: cstring): bool =
# loadFromData(self, uint8Array(data), -1) # loadFromData(self, uint8Array(data), -1)
proc addAction*(self: ApplicationWindow; action: Action | PropertyAction | SimpleAction) =
g_action_map_add_action(cast[ptr ActionMap00](self.impl), cast[ptr Action00](action.impl))
proc gtk_file_chooser_dialog_new*(title: cstring; parent: ptr Window00; action: FileChooserAction; proc gtk_file_chooser_dialog_new*(title: cstring; parent: ptr Window00; action: FileChooserAction;
firstButtonText: cstring = nil): ptr FileChooserDialog00 {.varargs, firstButtonText: cstring = nil): ptr FileChooserDialog00 {.varargs,
importc: "gtk_file_chooser_dialog_new", libprag.} importc: "gtk_file_chooser_dialog_new", libprag.}
@ -3062,7 +3086,8 @@ proc cstringArrayToSeq*(s: ptr cstring): seq[string] =
# if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE and gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == G_TYPE_BOXED: # if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE and gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == G_TYPE_BOXED:
# echo gBaseInfoGetName(info)#gRegisteredTypeInfoGetGType(info) # echo gBaseInfoGetName(info)#gRegisteredTypeInfoGetGType(info)
let n = gBaseInfoGetName(info) let n = gBaseInfoGetName(info)
if n[0] != '_' and not n.endsWith("Private") and not (namespace == "Gdk" and n.startsWith("Event")) and not (namespace == "Pango" and n.startsWith("Attribute")): if n[0] != '_' and not n.endsWith("Private") and not (namespace == "Gdk" and n.startsWith("Event")) and not (namespace ==
"Pango" and n.startsWith("Attribute")):
if gBaseInfoGetType(info) == GIInfoType.STRUCT: if gBaseInfoGetType(info) == GIInfoType.STRUCT:
if not ((gStructInfoIsGtypeStruct(info) and n != "ObjectClass")): if not ((gStructInfoIsGtypeStruct(info) and n != "ObjectClass")):
var lightObj = true var lightObj = true
@ -3497,7 +3522,10 @@ launch()
# if not xcallerAlloc.contains(el): # if not xcallerAlloc.contains(el):
# echo el # echo el
# 3500 lines defined # 3525 lines
# gtk_icon_view_get_tooltip_context bug Candidate
# gtk_tree_view_get_cursor bug
#
# troubles: gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == G_TYPE_BOXED: # troubles: gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == G_TYPE_BOXED:
#[ #[