1 // GtkSharp.Generation.StructField.cs - The Structure Field generation
2 // Class.
3 //
4 // Author: Mike Kestner <mkestner@ximian.com>
5 //
6 // Copyright (c) 2004-2005 Novell, Inc.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of version 2 of the GNU General Public
10 // License as published by the Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public
18 // License along with this program; if not, write to the
19 // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 // Boston, MA 02111-1307, USA.
21 
22 
23 namespace GtkSharp.Generation {
24 
25 	using System;
26 	using System.IO;
27 	using System.Xml;
28 
29 	public class StructField : FieldBase {
30 
31 		public static int bitfields;
32 
StructField(XmlElement elem, ClassBase container_type)33 		public StructField (XmlElement elem, ClassBase container_type) : base (elem, container_type) {}
34 
35 		protected override string DefaultAccess {
36 			get {
37 				if (IsPadding)
38 					return "private";
39 
40 				return "public";
41 			}
42 		}
43 
44 		int ArrayLength {
45 			get {
46 				if (!IsArray)
47 					return 0;
48 
49 				int result;
50 				try {
51 					result = Int32.Parse (elem.GetAttribute("array_len"));
52 				} catch (Exception) {
53 					Console.Write ("Non-numeric array_len: " + elem.GetAttribute("array_len"));
54 					Console.WriteLine (" warning: array field {0} incorrectly generated", Name);
55 					result = 0;
56 				}
57 				return result;
58 			}
59 		}
60 
61 		bool IsNullTermArray {
62 			get { return elem.GetAttributeAsBoolean ("null_term_array"); }
63 		}
64 
65 		public new string CSType {
66 			get {
67 				string type = base.CSType;
68 				if (IsArray)
69 					type += "[]";
70 				else if ((IsPointer || SymbolTable.Table.IsOpaque (CType)) && type != "string")
71 					type = "IntPtr";
72 
73 				return type;
74 			}
75 		}
76 
77 		bool visible = false;
78 		internal bool Visible {
79 			get {
80 				return visible;
81 			}
82 		}
83 
84 		public string EqualityName {
85 			get {
86 				SymbolTable table = SymbolTable.Table;
87 				string wrapped_name = SymbolTable.Table.MangleName (CName);
88 				IGeneratable gen = table [CType];
89 
90 				if (IsArray || gen is IAccessor)
91 					return StudlyName;
92 				else if (IsBitfield)
93 					return Name;
94 				else if (IsPointer && (gen is StructGen || gen is BoxedGen || gen is UnionGen))
95 					return Access != "private" ? wrapped_name : Name;
96 				else if (IsPointer && CSType != "string")
97 					return Name;
98 				else
99 					return Access == "public" ? StudlyName : Name;
100 			}
101 		}
102 
103 		public bool IsPadding {
104 			get {
105 				return (CName.StartsWith ("dummy") || CName.StartsWith ("padding"));
106 			}
107 		}
108 
109 		public bool IsPointer {
110 			get {
111 				return (CType.EndsWith ("*") || CType.EndsWith ("pointer"));
112 			}
113 		}
114 
115 		public new string Name {
116 			get {
117 				string result = "";
118 				if ((IsPointer || SymbolTable.Table.IsOpaque (CType)) && CSType != "string")
119 					result = "_";
120 				result += SymbolTable.Table.MangleName (CName);
121 
122 				return result;
123 			}
124 		}
125 
126 		public string StudlyName {
127 			get {
128 				string studly = base.Name;
129 				if (studly == "")
130 					throw new Exception ("API file must be regenerated with a current version of the GAPI parser. It is incompatible with this version of the GAPI code generator.");
131 
132 				return studly;
133 			}
134 		}
135 
Generate(GenerationInfo gen_info, string indent)136 		public override void Generate (GenerationInfo gen_info, string indent)
137 		{
138 			if (Hidden)
139 				return;
140 
141 			visible = Access != "private";
142 
143 			StreamWriter sw = gen_info.Writer;
144 			SymbolTable table = SymbolTable.Table;
145 
146 			string wrapped = table.GetCSType (CType);
147 			string wrapped_name = SymbolTable.Table.MangleName (CName);
148 			IGeneratable gen = table [CType];
149 
150 			if (IsArray && !IsNullTermArray) {
151 				sw.WriteLine (indent + "[MarshalAs (UnmanagedType.ByValArray, SizeConst=" + ArrayLength + ")]");
152 				sw.WriteLine (indent + "{0} {1} {2};", Access, CSType, StudlyName);
153 			} else if (IsArray && IsNullTermArray) {
154 				sw.WriteLine (indent + "private {0} {1};", "IntPtr", StudlyName+ "Ptr");
155 				if ((Readable || Writable) && Access == "public") {
156 					sw.WriteLine (indent + "public {0} {1} {{", CSType, StudlyName);
157 					if (Readable)
158 						sw.WriteLine (indent + "\tget {{ return GLib.Marshaller.StructArrayFromNullTerminatedIntPtr<{0}> ({1}); }}",
159 						              base.CSType, StudlyName + "Ptr");
160 					if (Writable)
161 						sw.WriteLine (indent + "\tset {{ {0} = GLib.Marshaller.StructArrayToNullTerminatedStructArrayIntPtr<{1}> (value); }}",
162 						              StudlyName + "Ptr", base.CSType);
163 					sw.WriteLine (indent + "}");
164 				}
165 			} else if (IsBitfield) {
166 				base.Generate (gen_info, indent);
167 			} else if (gen is IAccessor) {
168 				sw.WriteLine (indent + "private {0} {1};", gen.MarshalType, Name);
169 
170 				if (Access != "private") {
171 					IAccessor acc = table [CType] as IAccessor;
172 					sw.WriteLine (indent + Access + " " + wrapped + " " + StudlyName + " {");
173 					acc.WriteAccessors (sw, indent + "\t", Name);
174 					sw.WriteLine (indent + "}");
175 				}
176 			} else if (IsPointer && (gen is StructGen || gen is BoxedGen || gen is UnionGen)) {
177 				sw.WriteLine (indent + "private {0} {1};", CSType, Name);
178 				sw.WriteLine ();
179 				if (Access != "private") {
180 					sw.WriteLine (indent + Access + " " + wrapped + " " + wrapped_name + " {");
181 					sw.WriteLine (indent + "\tget { return " + table.FromNative (CType, Name) + "; }");
182 					sw.WriteLine (indent + "}");
183 				}
184 			} else if (IsPointer && CSType != "string") {
185 				// FIXME: probably some fields here which should be visible.
186 				visible = false;
187 				sw.WriteLine (indent + "private {0} {1};", CSType, Name);
188 			} else {
189 				sw.WriteLine (indent + "{0} {1} {2};", Access, CSType, Access == "public" ? StudlyName : Name);
190 			}
191 		}
192 	}
193 }
194 
195