Add translations for various sub-directories
[binutils-gdb.git] / gdb / python / py-color.c
blob3a90b620d5f900e0ff7b6757926b841f76de84ee
1 /* Python interface to ui_file_style::color objects.
3 Copyright (C) 2008-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
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
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include "python-internal.h"
22 #include "py-color.h"
23 #include "cli/cli-decode.h"
25 /* Colorspace constants and their values. */
26 static struct {
27 const char *name;
28 color_space value;
29 } colorspace_constants[] =
31 { "COLORSPACE_MONOCHROME", color_space::MONOCHROME },
32 { "COLORSPACE_ANSI_8COLOR", color_space::ANSI_8COLOR },
33 { "COLORSPACE_AIXTERM_16COLOR", color_space::AIXTERM_16COLOR },
34 { "COLORSPACE_XTERM_256COLOR", color_space::XTERM_256COLOR },
35 { "COLORSPACE_RGB_24BIT", color_space::RGB_24BIT },
38 /* A color. */
39 struct colorpy_object
41 PyObject_HEAD
43 /* Underlying value. */
44 ui_file_style::color color;
47 extern PyTypeObject colorpy_object_type;
49 /* See py-color.h. */
50 gdbpy_ref<>
51 create_color_object (const ui_file_style::color &color)
53 gdbpy_ref<colorpy_object> color_obj (PyObject_New (colorpy_object,
54 &colorpy_object_type));
56 if (color_obj == nullptr)
57 return nullptr;
59 color_obj->color = color;
60 return gdbpy_ref<> ((PyObject *) color_obj.release ());
63 /* See py-color.h. */
64 bool
65 gdbpy_is_color (PyObject *obj)
67 return PyObject_IsInstance (obj, (PyObject *) &colorpy_object_type);
70 /* See py-color.h. */
71 const ui_file_style::color &
72 gdbpy_get_color (PyObject *obj)
74 gdb_assert (gdbpy_is_color (obj));
75 colorpy_object *self = (colorpy_object *) obj;
76 return self->color;
79 /* Get an attribute. */
80 static PyObject *
81 get_attr (PyObject *obj, PyObject *attr_name)
83 if (! PyUnicode_Check (attr_name))
84 return PyObject_GenericGetAttr (obj, attr_name);
86 colorpy_object *self = (colorpy_object *) obj;
87 const ui_file_style::color &color = self->color;
89 if (! PyUnicode_CompareWithASCIIString (attr_name, "colorspace"))
91 int value = static_cast<int> (color.colorspace ());
92 return gdb_py_object_from_longest (value).release ();
95 if (! PyUnicode_CompareWithASCIIString (attr_name, "is_none"))
96 return PyBool_FromLong (color.is_none ());
98 if (! PyUnicode_CompareWithASCIIString (attr_name, "is_indexed"))
99 return PyBool_FromLong (color.is_indexed ());
101 if (! PyUnicode_CompareWithASCIIString (attr_name, "is_direct"))
102 return PyBool_FromLong (color.is_direct ());
104 if (color.is_indexed ()
105 && ! PyUnicode_CompareWithASCIIString (attr_name, "index"))
106 return gdb_py_object_from_longest (color.get_value ()).release ();
108 if (color.is_direct ()
109 && ! PyUnicode_CompareWithASCIIString (attr_name, "components"))
111 uint8_t rgb[3];
112 color.get_rgb (rgb);
114 gdbpy_ref<> rgb_objects[3];
115 for (int i = 0; i < 3; ++i)
117 rgb_objects[i] = gdb_py_object_from_ulongest (rgb[i]);
118 if (rgb_objects[i] == nullptr)
119 return nullptr;
122 PyObject *comp = PyTuple_New (3);
123 if (comp == nullptr)
124 return nullptr;
126 for (int i = 0; i < 3; ++i)
127 PyTuple_SET_ITEM (comp, i, rgb_objects[i].release ());
129 return comp;
132 return PyObject_GenericGetAttr (obj, attr_name);
135 /* Implementation of Color.escape_sequence (self, is_fg) -> str. */
137 static PyObject *
138 colorpy_escape_sequence (PyObject *self, PyObject *is_fg_obj)
140 if (!gdbpy_is_color (self))
142 PyErr_SetString (PyExc_RuntimeError,
143 _("Object is not gdb.Color."));
144 return nullptr;
147 if (! PyBool_Check (is_fg_obj))
149 PyErr_SetString (PyExc_RuntimeError,
150 _("A boolean argument is required."));
151 return nullptr;
154 bool is_fg = is_fg_obj == Py_True;
155 std::string s = gdbpy_get_color (self).to_ansi (is_fg);
157 return host_string_to_python_string (s.c_str ()).release ();
160 /* Object initializer; fills color with value.
162 Use: __init__(VALUE = None, COLORSPACE = None)
164 VALUE is a string, integer, RGB-tuple or None.
166 COLORSPACE is the color space index.
168 Returns -1 on error, with a python exception set. */
170 static int
171 colorpy_init (PyObject *self, PyObject *args, PyObject *kwds)
173 colorpy_object *obj = (colorpy_object *) self;
174 PyObject *value_obj = nullptr;
175 PyObject *colorspace_obj = nullptr;
176 color_space colorspace = color_space::MONOCHROME;
178 if (! PyArg_ParseTuple (args, "|OO", &value_obj, &colorspace_obj))
179 return -1;
183 if (colorspace_obj)
185 if (PyLong_Check (colorspace_obj))
187 long colorspace_id = -1;
188 if (! gdb_py_int_as_long (colorspace_obj, &colorspace_id))
189 return -1;
190 if (!color_space_safe_cast (&colorspace, colorspace_id))
191 error (_("colorspace %ld is out of range."), colorspace_id);
193 else if (colorspace_obj == Py_None)
194 colorspace_obj = nullptr;
195 else
196 error (_("colorspace must be None or integer"));
199 if (value_obj == nullptr || value_obj == Py_None)
200 obj->color = ui_file_style::color (colorspace, -1);
201 else if (PyLong_Check (value_obj))
203 long value = -1;
204 if (! gdb_py_int_as_long (value_obj, &value))
205 return -1;
206 if (value < 0 || value > INT_MAX)
207 error (_("value %ld is out of range."), value);
208 if (colorspace_obj)
209 obj->color = ui_file_style::color (colorspace, value);
210 else
211 obj->color = ui_file_style::color (value);
213 else if (PyTuple_Check (value_obj))
215 if (colorspace_obj == nullptr || colorspace != color_space::RGB_24BIT)
216 error (_("colorspace must be gdb.COLORSPACE_RGB_24BIT with "
217 "value of tuple type."));
218 Py_ssize_t tuple_size = PyTuple_Size (value_obj);
219 if (tuple_size < 0)
220 return -1;
221 if (tuple_size != 3)
222 error (_("Tuple value with RGB must be of size 3."));
223 uint8_t rgb[3];
224 for (int i = 0; i < 3; ++i)
226 PyObject *item = PyTuple_GetItem (value_obj, i);
227 if (!PyLong_Check (item))
228 error (_("Item %d of an RGB tuple must be integer."), i);
229 long item_value = -1;
230 if (!gdb_py_int_as_long (item, &item_value))
231 return -1;
232 if (item_value < 0 || item_value > UINT8_MAX)
233 error (_("RGB item %ld is out of byte range."), item_value);
234 rgb[i] = static_cast<uint8_t> (item_value);
237 obj->color = ui_file_style::color (rgb[0], rgb[1], rgb[2]);
239 else if (PyUnicode_Check (value_obj))
241 gdb::unique_xmalloc_ptr<char>
242 str (python_string_to_host_string (value_obj));
243 if (str == nullptr)
244 return -1;
245 obj->color = parse_var_color (str.get());
247 if (colorspace_obj != nullptr
248 && colorspace != obj->color.colorspace ())
249 error (_("colorspace doesn't match to the value."));
251 else
252 error (_("value must be one of None, integer, tuple or str."));
254 catch (const gdb_exception &except)
256 return gdbpy_handle_gdb_exception (-1, except);
259 Py_INCREF (self);
260 return 0;
263 static PyObject *
264 colorpy_str (PyObject *self)
266 colorpy_object *obj = reinterpret_cast<colorpy_object *> (self);
268 return PyUnicode_FromString (obj->color.to_string ().c_str ());
271 /* Initialize the 'color' module. */
272 static int
273 gdbpy_initialize_color (void)
275 for (auto & pair : colorspace_constants)
276 if (PyModule_AddIntConstant (gdb_module, pair.name,
277 static_cast<long> (pair.value)) < 0)
278 return -1;
280 colorpy_object_type.tp_new = PyType_GenericNew;
281 return gdbpy_type_ready (&colorpy_object_type, gdb_module);
284 /* Color methods. */
286 static PyMethodDef color_methods[] =
288 { "escape_sequence", colorpy_escape_sequence, METH_O,
289 "escape_sequence (is_foreground) -> str.\n\
290 Return the ANSI escape sequence for this color.\n\
291 IS_FOREGROUND indicates whether this is a foreground or background color."},
292 {nullptr}
295 PyTypeObject colorpy_object_type =
297 PyVarObject_HEAD_INIT (nullptr, 0)
298 "gdb.Color", /*tp_name*/
299 sizeof (colorpy_object), /*tp_basicsize*/
300 0, /*tp_itemsize*/
301 0, /*tp_dealloc*/
302 0, /*tp_print*/
303 0, /*tp_getattr*/
304 0, /*tp_setattr*/
305 0, /*tp_compare*/
306 0, /*tp_repr*/
307 0, /*tp_as_number*/
308 0, /*tp_as_sequence*/
309 0, /*tp_as_mapping*/
310 0, /*tp_hash */
311 0, /*tp_call*/
312 colorpy_str, /*tp_str*/
313 get_attr, /*tp_getattro*/
314 0, /*tp_setattro*/
315 0, /*tp_as_buffer*/
316 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
317 "GDB color object", /* tp_doc */
318 0, /* tp_traverse */
319 0, /* tp_clear */
320 0, /* tp_richcompare */
321 0, /* tp_weaklistoffset */
322 0, /* tp_iter */
323 0, /* tp_iternext */
324 color_methods, /* tp_methods */
325 0, /* tp_members */
326 0, /* tp_getset */
327 0, /* tp_base */
328 0, /* tp_dict */
329 0, /* tp_descr_get */
330 0, /* tp_descr_set */
331 0, /* tp_dictoffset */
332 colorpy_init, /* tp_init */
333 0, /* tp_alloc */
336 GDBPY_INITIALIZE_FILE (gdbpy_initialize_color);