blob: 226b7d47e9e4e8731b8c2689c36b71e56b4320e8 [file] [log] [blame]
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001/*
2 * Copyright (c) 2002, Adam Dunkels.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided
13 * with the distribution.
14 * 3. All advertising materials mentioning features or use of this
15 * software must display the following acknowledgement:
16 * This product includes software developed by Adam Dunkels.
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * This file is part of the "ctk" console GUI toolkit for cc65
34 *
adamdunkelseb9bf6c2003-06-30 20:45:50 +000035 * $Id: ctk.h,v 1.11 2003/06/30 20:45:50 adamdunkels Exp $
adamdunkelsca9ddcb2003-03-19 14:13:31 +000036 *
37 */
38
39#ifndef __CTK_H__
40#define __CTK_H__
41
42#include "ctk-conf.h"
43#include "ek.h"
44
adamdunkels78c03dc2003-04-09 13:45:05 +000045#include "cc.h"
46
adamdunkelsca9ddcb2003-03-19 14:13:31 +000047/* Defintions for the CTK widget types. */
48#define CTK_WIDGET_SEPARATOR 1
49#define CTK_WIDGET_LABEL 2
50#define CTK_WIDGET_BUTTON 3
51#define CTK_WIDGET_HYPERLINK 4
52#define CTK_WIDGET_TEXTENTRY 5
adamdunkels1d5eb5e2003-03-28 12:10:39 +000053#define CTK_WIDGET_BITMAP 6
54#define CTK_WIDGET_ICON 7
adamdunkelsca9ddcb2003-03-19 14:13:31 +000055
56struct ctk_widget;
57
58#define CTK_SEPARATOR(x, y, w) \
adamdunkelseb9bf6c2003-06-30 20:45:50 +000059 NULL, NULL, x, y, CTK_WIDGET_SEPARATOR, w, 1
adamdunkelsca9ddcb2003-03-19 14:13:31 +000060struct ctk_separator {
61 struct ctk_widget *next;
62 struct ctk_window *window;
63 unsigned char x, y;
64 unsigned char type;
adamdunkelseb9bf6c2003-06-30 20:45:50 +000065 unsigned char w, h;
adamdunkelsca9ddcb2003-03-19 14:13:31 +000066};
67
68#define CTK_BUTTON(x, y, w, text) \
adamdunkelseb9bf6c2003-06-30 20:45:50 +000069 NULL, NULL, x, y, CTK_WIDGET_BUTTON, w, 1, text
adamdunkelsca9ddcb2003-03-19 14:13:31 +000070struct ctk_button {
71 struct ctk_widget *next;
72 struct ctk_window *window;
73 unsigned char x, y;
74 unsigned char type;
adamdunkelseb9bf6c2003-06-30 20:45:50 +000075 unsigned char w, h;
adamdunkelsca9ddcb2003-03-19 14:13:31 +000076 char *text;
77};
78
79#define CTK_LABEL(x, y, w, h, text) \
adamdunkelseb9bf6c2003-06-30 20:45:50 +000080 NULL, NULL, x, y, CTK_WIDGET_LABEL, w, h, text,
adamdunkelsca9ddcb2003-03-19 14:13:31 +000081struct ctk_label {
82 struct ctk_widget *next;
83 struct ctk_window *window;
84 unsigned char x, y;
85 unsigned char type;
adamdunkelseb9bf6c2003-06-30 20:45:50 +000086 unsigned char w, h;
adamdunkelsca9ddcb2003-03-19 14:13:31 +000087 char *text;
adamdunkelsca9ddcb2003-03-19 14:13:31 +000088};
89
90#define CTK_HYPERLINK(x, y, w, text, url) \
adamdunkelseb9bf6c2003-06-30 20:45:50 +000091 NULL, NULL, x, y, CTK_WIDGET_HYPERLINK, w, 1, text, url
adamdunkelsca9ddcb2003-03-19 14:13:31 +000092struct ctk_hyperlink {
93 struct ctk_widget *next;
94 struct ctk_window *window;
95 unsigned char x, y;
96 unsigned char type;
adamdunkelseb9bf6c2003-06-30 20:45:50 +000097 unsigned char w, h;
adamdunkelsca9ddcb2003-03-19 14:13:31 +000098 char *text;
99 char *url;
100};
101
102/* Editing modes of the CTK textentry widget. */
103#define CTK_TEXTENTRY_NORMAL 0
104#define CTK_TEXTENTRY_EDIT 1
105
106
107#define CTK_TEXTENTRY(x, y, w, h, text, len) \
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000108 NULL, NULL, x, y, CTK_WIDGET_TEXTENTRY, w, h, text, len, \
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000109 CTK_TEXTENTRY_NORMAL, 0, 0
110struct ctk_textentry {
111 struct ctk_widget *next;
112 struct ctk_window *window;
113 unsigned char x, y;
114 unsigned char type;
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000115 unsigned char w, h;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000116 char *text;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000117 unsigned char len;
118 unsigned char state;
119 unsigned char xpos, ypos;
120};
121
122
123#define CTK_ICON(title, bitmap, textmap) \
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000124 NULL, NULL, 0, 0, CTK_WIDGET_ICON, 2, 4, title, 0, bitmap, textmap
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000125struct ctk_icon {
126 struct ctk_widget *next;
127 struct ctk_window *window;
128 unsigned char x, y;
129 unsigned char type;
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000130 unsigned char w, h;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000131 char *title;
132 ek_id_t owner;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000133 unsigned char *bitmap;
134 char *textmap;
135};
136
137#define CTK_BITMAP(x, y, w, h, bitmap) \
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000138 NULL, NULL, x, y, CTK_WIDGET_BITMAP, w, h, bitmap,
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000139struct ctk_bitmap {
140 struct ctk_widget *next;
141 struct ctk_window *window;
142 unsigned char x, y;
143 unsigned char type;
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000144 unsigned char w, h;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000145 unsigned char *bitmap;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000146};
147
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000148#define CTK_TEXTMAP_NORMAL 0
149#define CTK_TEXTMAP_ACTIVE 1
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000150
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000151#define CTK_TEXTMAP(x, y, w, h, textmap, flags) \
152 NULL, NULL, x, y, CTK_WIDGET_LABEL, w, h, text, flags, CTK_TEXTMAP_NORMAL
153struct ctk_textmap {
154 struct ctk_widget *next;
155 struct ctk_window *window;
156 unsigned char x, y;
157 unsigned char type;
158 unsigned char w, h;
159 char *textmap;
160 unsigned char flags;
161 unsigned char state;
162};
163
164
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000165
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000166struct ctk_widget_button {
167 char *text;
168};
169
170struct ctk_widget_label {
171 char *text;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000172};
173
174struct ctk_widget_hyperlink {
175 char *text;
176 char *url;
177};
178
179struct ctk_widget_textentry {
180 char *text;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000181 unsigned char len;
182 unsigned char state;
183 unsigned char xpos, ypos;
184};
185
186struct ctk_widget_icon {
187 char *title;
188 ek_id_t owner;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000189 unsigned char *bitmap;
190 char *textmap;
191};
192
193struct ctk_widget_bitmap {
194 unsigned char *bitmap;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000195};
196
197struct ctk_widget {
198 struct ctk_widget *next;
199 struct ctk_window *window;
200 unsigned char x, y;
201 unsigned char type;
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000202 unsigned char w, h;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000203 union {
204 struct ctk_widget_label label;
205 struct ctk_widget_button button;
206 struct ctk_widget_hyperlink hyperlink;
207 struct ctk_widget_textentry textentry;
208 struct ctk_widget_icon icon;
adamdunkels1d5eb5e2003-03-28 12:10:39 +0000209 struct ctk_widget_bitmap bitmap;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000210 } widget;
211};
212
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000213struct ctk_desktop;
214
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000215/* Definition of the CTK window structure. */
216struct ctk_window {
217 struct ctk_window *next, *prev;
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000218 struct ctk_desktop *desktop;
219
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000220 ek_id_t owner;
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000221
adamdunkels1d5eb5e2003-03-28 12:10:39 +0000222 char *title;
223 unsigned char titlelen;
224
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000225#if CTK_CONF_WINDOWCLOSE
226 struct ctk_button closebutton;
227#else /* CTK_CONF_WINDOWCLOSE */
228 struct ctk_label closebutton;
229#endif /* CTK_CONF_WINDOWCLOSE */
230
231#if CTK_CONF_WINDOWMOVE
232 struct ctk_button titlebutton;
233#else /* CTK_CONF_WINDOWMOVE */
234 struct ctk_label titlebutton;
235#endif /* CTK_CONF_WINDOWMOVE */
236
adamdunkels1d5eb5e2003-03-28 12:10:39 +0000237 unsigned char x, y;
238 unsigned char w, h;
239
240
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000241 struct ctk_widget *inactive;
242 struct ctk_widget *active;
243 struct ctk_widget *focused;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000244};
245
246struct ctk_menuitem {
247 char *title;
248 unsigned char titlelen;
249};
250
251struct ctk_menu {
252 struct ctk_menu *next;
253 char *title;
254 unsigned char titlelen;
adamdunkels78c03dc2003-04-09 13:45:05 +0000255#if CC_UNSIGNED_CHAR_BUGS
adamdunkels6ccf7212003-04-10 07:04:45 +0000256 unsigned int nitems;
257 unsigned int active;
adamdunkels78c03dc2003-04-09 13:45:05 +0000258#else /* CC_UNSIGNED_CHAR_BUGS */
259 unsigned char nitems;
260 unsigned char active;
261#endif /* CC_UNSIGNED_CHAR_BUGS */
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000262 struct ctk_menuitem items[CTK_CONF_MAXMENUITEMS];
263};
264
265struct ctk_menus {
266 struct ctk_menu *menus;
267 struct ctk_menu *open;
268 struct ctk_menu *desktopmenu;
269};
270
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000271/* Definition of the CTK desktop structure. */
272struct ctk_desktop {
273 char *name;
274
275 struct ctk_window desktop_window;
276 struct ctk_window *windows;
277 struct ctk_window *dialog;
278
279#if CTK_CONF_MENUS
280 struct ctk_menus menus;
281 struct ctk_menu *lastmenu;
282 struct ctk_menu desktopmenu;
283#endif /* CTK_CONF_MENUS */
284
285 unsigned char height, width;
286
287#define CTK_REDRAW_NONE 0
288#define CTK_REDRAW_ALL 1
289#define CTK_REDRAW_WINDOWS 2
290#define CTK_REDRAW_WIDGETS 4
291#define CTK_REDRAW_MENUS 8
292#define CTK_REDRAW_PART 16
293
294#ifndef CTK_CONF_MAX_REDRAWWIDGETS
295#define CTK_CONF_MAX_REDRAWWIDGETS 8
296#endif /* CTK_CONF_MAX_REDRAWWIDGETS */
297#ifndef CTK_CONF_MAX_REDRAWWINDOWS
298#define CTK_CONF_MAX_REDRAWWINDOWS 8
299#endif /* CTK_CONF_MAX_REDRAWWINDOWS */
300
301
302
303 unsigned char redraw;
304
305 struct ctk_widget *redraw_widgets[CTK_CONF_MAX_REDRAWWIDGETS];
306 unsigned char redraw_widgetptr;
307
308 struct ctk_window *redraw_windows[CTK_CONF_MAX_REDRAWWINDOWS];
309 unsigned char redraw_windowptr;
310
311
312 unsigned char redraw_y1, redraw_y2;
313};
314
315
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000316/* Global CTK modes. */
317#define CTK_MODE_NORMAL 0
318#define CTK_MODE_WINDOWMOVE 1
319#define CTK_MODE_SCREENSAVER 2
320#define CTK_MODE_EXTERNAL 3
321
322/* General ctk functions. */
323void ctk_init(void);
324void ctk_mode_set(unsigned char mode);
325unsigned char ctk_mode_get(void);
326void ctk_redraw(void);
327
328/* Functions for manipulating windows. */
329void ctk_window_new(struct ctk_window *window,
330 unsigned char w, unsigned char h,
331 char *title);
332void ctk_window_clear(struct ctk_window *w);
333void ctk_window_open(struct ctk_window *w);
334#define ctk_window_move(w,xpos,ypos) do {(w)->x=xpos; (w)->y=ypos;}while(0)
335void ctk_window_close(struct ctk_window *w);
336void ctk_window_redraw(struct ctk_window *w);
337#define ctk_window_isopen(w) ((w)->next != NULL)
338
339
340/* Functions for manipulating dialogs. */
341void ctk_dialog_new(struct ctk_window *window,
342 unsigned char w, unsigned char h);
343void ctk_dialog_open(struct ctk_window *d);
344void ctk_dialog_close(void);
345
346/* Functions for manipulating menus. */
347void ctk_menu_new(struct ctk_menu *menu, char *title);
348void ctk_menu_add(struct ctk_menu *menu);
349void ctk_menu_remove(struct ctk_menu *menu);
350unsigned char ctk_menuitem_add(struct ctk_menu *menu, char *name);
351
352/* Functions for icons. */
353#define CTK_ICON_ADD(icon, id) ctk_icon_add((struct ctk_widget *)icon, id)
354void ctk_icon_add(struct ctk_widget *icon, ek_id_t id);
355
356/* Functions for manipulating widgets. */
357#define CTK_WIDGET_ADD(win, widg) \
358 ctk_widget_add(win, (struct ctk_widget *)widg)
359void ctk_widget_add(struct ctk_window *window,
360 struct ctk_widget *widget);
361
362#define CTK_WIDGET_FOCUS(win, widg) \
363 (win)->focused = (struct ctk_widget *)(widg)
364#define CTK_WIDGET_REDRAW(widg) \
365 ctk_widget_redraw((struct ctk_widget *)widg)
366void ctk_widget_redraw(struct ctk_widget *w);
367
adamdunkels3a08a492003-04-11 20:16:02 +0000368#define CTK_WIDGET_TYPE(w) ((w)->type)
369
adamdunkelse8b21d02003-04-24 17:18:27 +0000370#define CTK_WIDGET_SET_XPOS(w, xpos) ((struct ctk_widget *)(w))->x = (xpos)
371#define CTK_WIDGET_SET_YPOS(w, ypos) ((struct ctk_widget *)(w))->y = (ypos)
372
373#define CTK_WIDGET_SET_WIDTH(widget, width) do { \
374 ((struct ctk_widget *)(widget))->w = (width); } while(0)
375
376#define CTK_WIDGET_XPOS(w) (((struct ctk_widget *)(w))->x)
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000377#define CTK_WIDGET_YPOS(w) (((struct ctk_widget *)(w))->y)
378
379#define ctk_textentry_set_height(w, height) \
380 (w)->widget.textentry.h = (height)
381#define ctk_label_set_height(w, height) \
382 (w)->widget.label.h = (height)
383#define ctk_label_set_text(l, t) (l)->text = (t)
384
adamdunkels1d5eb5e2003-03-28 12:10:39 +0000385#define ctk_button_set_text(b, t) (b)->text = (t)
386
adamdunkels58917a82003-04-18 00:18:38 +0000387#define ctk_bitmap_set_bitmap(b, m) (b)->bitmap = (m)
388
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000389#define CTK_BUTTON_NEW(widg, xpos, ypos, width, buttontext) \
390 (widg)->window = NULL; \
391 (widg)->next = NULL; \
392 (widg)->type = CTK_WIDGET_BUTTON; \
393 (widg)->x = (xpos); \
394 (widg)->y = (ypos); \
395 (widg)->w = (width); \
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000396 (widg)->h = 1; \
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000397 (widg)->text = (buttontext)
398
399#define CTK_LABEL_NEW(widg, xpos, ypos, width, height, labeltext) \
400 (widg)->window = NULL; \
401 (widg)->next = NULL; \
402 (widg)->type = CTK_WIDGET_LABEL; \
403 (widg)->x = (xpos); \
404 (widg)->y = (ypos); \
405 (widg)->w = (width); \
406 (widg)->h = (height); \
407 (widg)->text = (labeltext)
408
adamdunkels58917a82003-04-18 00:18:38 +0000409#define CTK_BITMAP_NEW(widg, xpos, ypos, width, height, bmap) \
410 (widg)->window = NULL; \
411 (widg)->next = NULL; \
412 (widg)->type = CTK_WIDGET_BITMAP; \
413 (widg)->x = (xpos); \
414 (widg)->y = (ypos); \
415 (widg)->w = (width); \
416 (widg)->h = (height); \
417 (widg)->bitmap = (bmap)
418
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000419#define CTK_TEXTENTRY_NEW(widg, xxpos, yypos, width, height, textptr, textlen) \
420 (widg)->window = NULL; \
421 (widg)->next = NULL; \
422 (widg)->type = CTK_WIDGET_TEXTENTRY; \
423 (widg)->x = (xxpos); \
424 (widg)->y = (yypos); \
425 (widg)->w = (width); \
426 (widg)->h = (height); \
427 (widg)->text = (textptr); \
428 (widg)->len = (textlen); \
429 (widg)->state = CTK_TEXTENTRY_NORMAL; \
430 (widg)->xpos = 0; \
431 (widg)->ypos = 0
432
433
434
435#define CTK_HYPERLINK_NEW(widg, xpos, ypos, width, linktext, linkurl) \
436 (widg)->window = NULL; \
437 (widg)->next = NULL; \
438 (widg)->type = CTK_WIDGET_HYPERLINK; \
439 (widg)->x = (xpos); \
440 (widg)->y = (ypos); \
441 (widg)->w = (width); \
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000442 (widg)->h = 1; \
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000443 (widg)->text = (linktext); \
444 (widg)->url = (linkurl)
445
adamdunkelse2f4d2a2003-04-28 23:21:42 +0000446/* Desktop interface. */
adamdunkelseb9bf6c2003-06-30 20:45:50 +0000447void ctk_desktop_redraw(struct ctk_desktop *d);
448unsigned char ctk_desktop_width(struct ctk_desktop *d);
449unsigned char ctk_desktop_height(struct ctk_desktop *d);
adamdunkelse2f4d2a2003-04-28 23:21:42 +0000450
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000451/* Signals. */
452extern ek_signal_t ctk_signal_keypress,
adamdunkels3a08a492003-04-11 20:16:02 +0000453 ctk_signal_widget_activate,
454 ctk_signal_widget_select,
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000455 ctk_signal_timer,
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000456 ctk_signal_menu_activate,
adamdunkelsc4902862003-04-09 00:30:45 +0000457 ctk_signal_window_close,
458 ctk_signal_pointer_move,
adamdunkels3a08a492003-04-11 20:16:02 +0000459 ctk_signal_pointer_button;
460
adamdunkelse8b21d02003-04-24 17:18:27 +0000461#if CTK_CONF_SCREENSAVER
462extern ek_signal_t ctk_signal_screensaver_start,
463 ctk_signal_screensaver_stop,
464 ctk_signal_screensaver_uninstall;
adamdunkelse2f4d2a2003-04-28 23:21:42 +0000465
466extern unsigned short ctk_screensaver_timeout;
467#define CTK_SCREENSAVER_SET_TIMEOUT(t) ctk_screensaver_timeout = (t)
468#define CTK_SCREENSAVER_TIMEOUT() ctk_screensaver_timeout
adamdunkelse8b21d02003-04-24 17:18:27 +0000469#endif /* CTK_CONF_SCREENSAVER */
470
adamdunkels3a08a492003-04-11 20:16:02 +0000471/* These should no longer be used: */
472extern ek_signal_t ctk_signal_button_activate,
473 ctk_signal_button_hover,
474 ctk_signal_hyperlink_activate,
475 ctk_signal_hyperlink_hover;
476
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000477/* Focus flags */
478#define CTK_FOCUS_NONE 0
479#define CTK_FOCUS_WIDGET 1
480#define CTK_FOCUS_WINDOW 2
481#define CTK_FOCUS_DIALOG 4
482
483
484
485#endif /* __CTK_H__ */