1 /*	Public domain	*/
2 
3 #ifndef _AGAR_GUI_EDITABLE_H_
4 #define _AGAR_GUI_EDITABLE_H_
5 
6 #include <agar/gui/widget.h>
7 #include <agar/gui/text.h>
8 
9 #include <agar/gui/begin.h>
10 
11 struct ag_popup_menu;
12 
13 /* Working UCS-4 text buffer for internal use */
14 typedef struct ag_editable_buffer {
15 	AG_Variable *var;		/* Variable binding (if any) */
16 	Uint32 *s;			/* String buffer (UCS-4 encoding) */
17 	size_t len;			/* String length (chars) */
18 	size_t maxLen;			/* Available buffer size (bytes) */
19 	int reallocable;		/* Buffer can be realloc'd */
20 } AG_EditableBuffer;
21 
22 /* Internal clipboard for copy/paste and kill/yank */
23 typedef struct ag_editable_clipboard {
24 	AG_Mutex lock;
25 	char encoding[32];		/* Character set encoding */
26 	Uint32 *s;			/* UCS-4 buffer */
27 	size_t len;			/* Length in characters */
28 } AG_EditableClipboard;
29 
30 typedef struct ag_editable {
31 	struct ag_widget wid;
32 
33 	Uint flags;
34 #define AG_EDITABLE_HFILL         0x000001
35 #define AG_EDITABLE_VFILL         0x000002
36 #define AG_EDITABLE_EXPAND        (AG_EDITABLE_HFILL|AG_EDITABLE_VFILL)
37 #define AG_EDITABLE_MULTILINE     0x000004 /* Multiline edition */
38 #define AG_EDITABLE_BLINK_ON      0x000008 /* Cursor blink state (internal) */
39 #define AG_EDITABLE_PASSWORD      0x000010 /* Password (hidden) input */
40 #define AG_EDITABLE_ABANDON_FOCUS 0x000020 /* Abandon focus on return */
41 #define AG_EDITABLE_INT_ONLY      0x000040 /* Accepts only int input */
42 #define AG_EDITABLE_FLT_ONLY      0x000080 /* Accepts only float input */
43 #define AG_EDITABLE_CATCH_TAB     0x000100 /* Process tab key input */
44 #define AG_EDITABLE_CURSOR_MOVING 0x000200 /* Cursor is being moved */
45 #define AG_EDITABLE_KEEPVISCURSOR 0x000800 /* Try to keep cursor visible */
46 #define AG_EDITABLE_MARKPREF      0x002000 /* Mark current cursor position */
47 #define AG_EDITABLE_EXCL          0x004000 /* Exclusive access to buffer */
48 #define AG_EDITABLE_NOEMACS       0x008000 /* Disable emacs-style fn keys */
49 #define AG_EDITABLE_NOLATIN1      0x020000 /* Disable LATIN-1 combinations */
50 #define AG_EDITABLE_WORDWRAP      0x040000 /* Word wrapping */
51 #define AG_EDITABLE_NOPOPUP	  0x080000 /* Disable popup menu */
52 #define AG_EDITABLE_WORDSELECT	  0x100000 /* Select whole words */
53 #define AG_EDITABLE_READONLY	  0x200000 /* Disable user input */
54 #define AG_EDITABLE_MULTILINGUAL  0x400000 /* Multilingual edition */
55 
56 	const char *encoding;		/* Character set (default "UTF-8") */
57 	AG_Text *text;			/* Default binding */
58 	int wPre, hPre;			/* Size hint */
59 	int pos;			/* Cursor position */
60 	int sel;			/* Selection offset / range */
61 	int selDblClick;		/* Double click position */
62 	Uint32 compose;			/* For input composition */
63 	int xCurs, yCurs;		/* Last cursor position */
64 	int xSelStart, ySelStart;	/* Last selection start position */
65 	int xSelEnd, ySelEnd;		/* Last selection end position */
66 	int xCursPref;			/* Requested cursor position */
67 	int x;				/* Horizontal offset (px) */
68 	int xMax;			/* Rightmost x of largest line (px) */
69 	int y;				/* Vertical offset (lines) */
70 	int yMax;			/* Lowest y (lines) */
71 	int yVis;			/* Maximum visible area (lines) */
72 	Uint32 wheelTicks;		/* For wheel acceleration */
73 	AG_EditableBuffer sBuf;		/* Working buffer (for STATIC) */
74 	AG_Rect r;			/* View area */
75 	AG_CursorArea *ca;		/* Text cursor-change area */
76 	int fontMaxHeight;		/* Maximum character height */
77 	int lineSkip;			/* Y-increment in multiline mode */
78 	struct ag_popup_menu *pm;	/* Right-click popup menu */
79 	enum ag_language lang;		/* Selected language (for AG_Text) */
80 	int xScrollPx;			/* Explicit scroll request in pixels */
81 	int *xScrollTo, *yScrollTo;	/* Scroll to specified position */
82 	AG_Timer toRepeat;		/* Key repeat timer */
83 	AG_Timer toCursorBlink;		/* Cursor blink timer */
84 	AG_Timer toDblClick;		/* Double click timer */
85 } AG_Editable;
86 
87 #define AGEDITABLE(p) ((AG_Editable *)(p))
88 #ifdef _AGAR_INTERNAL
89 #define EDITABLE(p) AGEDITABLE(p)
90 #endif
91 
92 __BEGIN_DECLS
93 extern AG_WidgetClass agEditableClass;
94 extern AG_EditableClipboard agEditableClipbrd;
95 extern AG_EditableClipboard agEditableKillring;
96 
97 AG_Editable *AG_EditableNew(void *, Uint);
98 void         AG_EditableBindUTF8(AG_Editable *, char *, size_t);
99 void         AG_EditableBindASCII(AG_Editable *, char *, size_t);
100 void         AG_EditableBindEncoded(AG_Editable *, const char *, char *, size_t);
101 void         AG_EditableBindText(AG_Editable *, AG_Text *);
102 void         AG_EditableSetLang(AG_Editable *, enum ag_language);
103 
104 AG_EditableBuffer *AG_EditableGetBuffer(AG_Editable *);
105 void               AG_EditableReleaseBuffer(AG_Editable *, AG_EditableBuffer *);
106 void               AG_EditableClearBuffer(AG_Editable *, AG_EditableBuffer *);
107 int                AG_EditableGrowBuffer(AG_Editable *, AG_EditableBuffer *,
108                                          Uint32 *, size_t);
109 
110 int  AG_EditableCut(AG_Editable *, AG_EditableBuffer *, AG_EditableClipboard *);
111 int  AG_EditableCopy(AG_Editable *, AG_EditableBuffer *, AG_EditableClipboard *);
112 void AG_EditableCopyChunk(AG_Editable *, AG_EditableClipboard *, Uint32 *,
113                           size_t);
114 int  AG_EditablePaste(AG_Editable *, AG_EditableBuffer *, AG_EditableClipboard *);
115 int  AG_EditableDelete(AG_Editable *, AG_EditableBuffer *);
116 void AG_EditableSelectAll(AG_Editable *, AG_EditableBuffer *);
117 
118 void         AG_EditableSizeHint(AG_Editable *, const char *);
119 void         AG_EditableSizeHintPixels(AG_Editable *, Uint, Uint);
120 void         AG_EditableSizeHintLines(AG_Editable *, Uint);
121 #define      AG_EditablePrescale AG_EditableSizeHint
122 void         AG_EditableSetPassword(AG_Editable *, int);
123 void         AG_EditableSetWordWrap(AG_Editable *, int);
124 void         AG_EditableSetExcl(AG_Editable *, int);
125 void         AG_EditableSetFltOnly(AG_Editable *, int);
126 void         AG_EditableSetIntOnly(AG_Editable *, int);
127 
128 void     AG_EditableSetString(AG_Editable *, const char *);
129 #define  AG_EditableClearString(tb) AG_EditableSetString((tb),NULL)
130 void     AG_EditablePrintf(void *, const char *, ...);
131 char    *AG_EditableDupString(AG_Editable *);
132 size_t   AG_EditableCopyString(AG_Editable *, char *, size_t)
133                                BOUNDED_ATTRIBUTE(__string__, 2, 3);
134 int      AG_EditableInt(AG_Editable *);
135 float    AG_EditableFlt(AG_Editable *);
136 double   AG_EditableDbl(AG_Editable *);
137 
138 void     AG_EditableInitClipboards(void);
139 void     AG_EditableDestroyClipboards(void);
140 
141 int  AG_EditableMapPosition(AG_Editable *, AG_EditableBuffer *, int, int, int *);
142 void AG_EditableMoveCursor(AG_Editable *, AG_EditableBuffer *, int, int);
143 int  AG_EditableSetCursorPos(AG_Editable *, AG_EditableBuffer *, int);
144 
145 /* Return current cursor position in text. */
146 static __inline__ int
AG_EditableGetCursorPos(AG_Editable * ed)147 AG_EditableGetCursorPos(AG_Editable *ed)
148 {
149 	int rv;
150 	AG_ObjectLock(ed);
151 	rv = ed->pos;
152 	AG_ObjectUnlock(ed);
153 	return (rv);
154 }
155 
156 /* Return 1 if the Editable is effectively read-only. */
157 static __inline__ int
AG_EditableReadOnly(AG_Editable * ed)158 AG_EditableReadOnly(AG_Editable *ed)
159 {
160 	return (ed->flags & AG_EDITABLE_READONLY) || AG_WidgetDisabled(ed);
161 }
162 
163 /*
164  * Ensure that the selection range is valid. The Editable and buffer
165  * must both be locked.
166  */
167 static __inline__ void
AG_EditableValidateSelection(AG_Editable * ed,AG_EditableBuffer * buf)168 AG_EditableValidateSelection(AG_Editable *ed, AG_EditableBuffer *buf)
169 {
170 	if ((Uint)ed->pos > buf->len) {
171 		ed->pos = (int)buf->len;
172 		ed->sel = 0;
173 	}
174 	if (ed->sel != 0) {
175 		int ep = ed->pos + ed->sel;
176 		if (ep < 0) {
177 			ed->pos = 0;
178 			ed->sel = 0;
179 		} else if ((Uint)ep > buf->len) {
180 			ed->pos = (int)buf->len;
181 			ed->sel = 0;
182 		}
183 	}
184 }
185 
186 #ifdef AG_LEGACY
187 # define AG_EditableSetFont AG_SetFont
188 # define AG_EditableSetStatic AG_EditableSetExcl
189 # define AG_EDITABLE_STATIC AG_EDITABLE_EXCL
190 # define AG_EDITABLE_NOWORDSEEK 0
191 # define AG_EditableSetWriteable(tb,flag) do {	\
192 	if (flag) {				\
193 	 	AG_WidgetEnable(tb);		\
194 	} else {				\
195 		AG_WidgetDisable(tb);		\
196 	}					\
197 } while (0)
198 #endif /* AG_LEGACY */
199 
200 __END_DECLS
201 
202 #include <agar/gui/close.h>
203 #endif /* _AGAR_GUI_EDITABLE_H_ */
204