aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuuki Harano2019-11-13 23:36:27 +0900
committerJeff Walsh2020-11-22 14:46:56 +1100
commit232c129fe4ccc091c6b403a4d72b51d3d9687e23 (patch)
tree0c5e90932a6c61e5d4b9608193ff855e9a5e8063 /src
parent9e56fa9853f5d0114b90d69ff43885a80ca8f5bd (diff)
downloademacs-232c129fe4ccc091c6b403a4d72b51d3d9687e23.tar.gz
emacs-232c129fe4ccc091c6b403a4d72b51d3d9687e23.zip
implement pre-edit input method
* src/termhooks.h (enum event_kind): new pgtk value * src/pgtkterm.h (struct pgtk_display_info): * src/pgtkterm.c (x_free_frame_resources, pgtk_delete_terminal) (pgtk_enqueue_string, pgtk_enqueue_preedit, key_press_event) (focus_in_event, focus_out_event, pgtk_term_init): call pgtkim * src/pgtkim.c: new file (im_context_commit_cb, im_context_retrieve_surrounding_cb) (make_color_string, im_context_preedit_changed_cb) (im_context_preedit_end_cb, im_context_preedit_start_cb) (pgtk_im_focus_in, pgtk_im_focus_out, pgtk_im_filter_keypress) (pgtk_im_finish, Fpgtk_use_im_context, syms_of_pgtkim): * src/pgtkfns.c (check_pgtk_display_info): * src/keyboard.c (kbd_buffer_get_event, make_lispy_event) (keys_of_keyboard): * src/emacs.c (main): add syms_of_pgtkim * lisp/term/pgtk-win.el (pgtk-preedit-text): new defun * configure.ac (XWIDGETS_OBJ): add pgtkim.o input method 対応 preedit を overlay で表示するようにした。 preedit 表示後すぐに反映されなかったのを修正 この機能を ON/OFF できるようにした。 default off. 確定と同時に次の preedit が始まった場合に表示位置がおかしかったのを修正。 sample. preedit をテキストで渡すようにした
Diffstat (limited to 'src')
-rw-r--r--src/emacs.c1
-rw-r--r--src/keyboard.c10
-rw-r--r--src/pgtkfns.c2
-rw-r--r--src/pgtkim.c243
-rw-r--r--src/pgtkterm.c55
-rw-r--r--src/pgtkterm.h19
-rw-r--r--src/termhooks.h4
7 files changed, 333 insertions, 1 deletions
diff --git a/src/emacs.c b/src/emacs.c
index 42d93737b93..ba5c64a1525 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1922,6 +1922,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1922 syms_of_pgtkfns(); 1922 syms_of_pgtkfns();
1923 syms_of_pgtkselect (); 1923 syms_of_pgtkselect ();
1924 syms_of_pgtkmenu (); 1924 syms_of_pgtkmenu ();
1925 syms_of_pgtkim ();
1925 syms_of_fontset (); 1926 syms_of_fontset ();
1926 syms_of_xsettings (); 1927 syms_of_xsettings ();
1927 syms_of_xwidget (); 1928 syms_of_xwidget ();
diff --git a/src/keyboard.c b/src/keyboard.c
index 49261fcc3e8..f6c44a11fb9 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -3939,6 +3939,9 @@ kbd_buffer_get_event (KBOARD **kbp,
3939 *used_mouse_menu = true; 3939 *used_mouse_menu = true;
3940 FALLTHROUGH; 3940 FALLTHROUGH;
3941#endif 3941#endif
3942#ifdef HAVE_PGTK
3943 case PGTK_PREEDIT_TEXT_EVENT:
3944#endif
3942#ifdef HAVE_NTGUI 3945#ifdef HAVE_NTGUI
3943 case END_SESSION_EVENT: 3946 case END_SESSION_EVENT:
3944 case LANGUAGE_CHANGE_EVENT: 3947 case LANGUAGE_CHANGE_EVENT:
@@ -6047,6 +6050,11 @@ make_lispy_event (struct input_event *event)
6047 return list3 (Qconfig_changed_event, 6050 return list3 (Qconfig_changed_event,
6048 event->arg, event->frame_or_window); 6051 event->arg, event->frame_or_window);
6049 6052
6053#ifdef HAVE_PGTK
6054 case PGTK_PREEDIT_TEXT_EVENT:
6055 return list2 (intern("pgtk-preedit-text"), event->arg);
6056#endif
6057
6050 /* The 'kind' field of the event is something we don't recognize. */ 6058 /* The 'kind' field of the event is something we don't recognize. */
6051 default: 6059 default:
6052 emacs_abort (); 6060 emacs_abort ();
@@ -12451,6 +12459,8 @@ keys_of_keyboard (void)
12451 "ns-put-working-text"); 12459 "ns-put-working-text");
12452 initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text", 12460 initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text",
12453 "ns-unput-working-text"); 12461 "ns-unput-working-text");
12462 initial_define_lispy_key (Vspecial_event_map, "pgtk-preedit-text",
12463 "pgtk-preedit-text");
12454 /* Here we used to use `ignore-event' which would simple set prefix-arg to 12464 /* Here we used to use `ignore-event' which would simple set prefix-arg to
12455 current-prefix-arg, as is done in `handle-switch-frame'. 12465 current-prefix-arg, as is done in `handle-switch-frame'.
12456 But `handle-switch-frame is not run from the special-map. 12466 But `handle-switch-frame is not run from the special-map.
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 090ebf5b363..2525547c3f7 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -60,7 +60,7 @@ static const char *pgtk_app_name = "Emacs";
60 60
61 ========================================================================== */ 61 ========================================================================== */
62 62
63static struct pgtk_display_info * 63struct pgtk_display_info *
64check_pgtk_display_info (Lisp_Object object) 64check_pgtk_display_info (Lisp_Object object)
65{ 65{
66 struct pgtk_display_info *dpyinfo = NULL; 66 struct pgtk_display_info *dpyinfo = NULL;
diff --git a/src/pgtkim.c b/src/pgtkim.c
new file mode 100644
index 00000000000..d9bba7e5904
--- /dev/null
+++ b/src/pgtkim.c
@@ -0,0 +1,243 @@
1/* Pure Gtk+-3 communication module. -*- coding: utf-8 -*-
2
3Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2018 Free Software
4Foundation, Inc.
5
6This file is part of GNU Emacs.
7
8GNU Emacs is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or (at
11your option) any later version.
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
20
21/* This should be the first include, as it may set up #defines affecting
22 interpretation of even the system includes. */
23#include <config.h>
24
25#include "pgtkterm.h"
26
27static void im_context_commit_cb(GtkIMContext *imc, gchar *str, gpointer user_data)
28{
29 struct pgtk_display_info *dpyinfo = user_data;
30 struct frame *f = dpyinfo->im.focused_frame;
31
32 if (dpyinfo->im.context == NULL)
33 return;
34 if (f == NULL)
35 return;
36
37 pgtk_enqueue_string(f, str);
38}
39
40static gboolean im_context_retrieve_surrounding_cb(GtkIMContext *imc, gpointer user_data)
41{
42 gtk_im_context_set_surrounding(imc, "", -1, 0);
43 return TRUE;
44}
45
46static gboolean im_context_delete_surrounding_cb(GtkIMContext *imc, int offset, int n_chars, gpointer user_data)
47{
48 return TRUE;
49}
50
51static Lisp_Object make_color_string(PangoAttrColor *pac)
52{
53 char buf[256];
54 sprintf(buf, "#%02x%02x%02x",
55 pac->color.red >> 8,
56 pac->color.green >> 8,
57 pac->color.blue >> 8);
58 return build_string(buf);
59}
60
61static void im_context_preedit_changed_cb(GtkIMContext *imc, gpointer user_data)
62{
63 struct pgtk_display_info *dpyinfo = user_data;
64 struct frame *f = dpyinfo->im.focused_frame;
65 char *str;
66 PangoAttrList *attrs;
67 int pos;
68
69 if (dpyinfo->im.context == NULL)
70 return;
71 if (f == NULL)
72 return;
73
74 gtk_im_context_get_preedit_string(imc, &str, &attrs, &pos);
75
76
77 /*
78 * (
79 * (TEXT (ul . COLOR) (bg . COLOR) (fg . COLOR))
80 * ...
81 * )
82 */
83 Lisp_Object list = Qnil;
84
85 PangoAttrIterator* iter;
86 iter = pango_attr_list_get_iterator(attrs);
87 do {
88 int st, ed;
89 int has_underline = 0;
90 Lisp_Object part = Qnil;
91
92 pango_attr_iterator_range(iter, &st, &ed);
93
94 if (ed > strlen(str))
95 ed = strlen(str);
96 if (st >= ed)
97 continue;
98
99 Lisp_Object text = make_string(str + st, ed - st);
100 part = Fcons(text, part);
101
102 PangoAttrInt *ul = (PangoAttrInt *) pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE);
103 if (ul != NULL) {
104 if (ul->value != PANGO_UNDERLINE_NONE)
105 has_underline = 1;
106 }
107
108 PangoAttrColor *pac;
109 if (has_underline) {
110 pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE_COLOR);
111 if (pac != NULL)
112 part = Fcons(Fcons(Qul, make_color_string(pac)), part);
113 else
114 part = Fcons(Fcons(Qul, Qt), part);
115 }
116
117 pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_FOREGROUND);
118 if (pac != NULL)
119 part = Fcons(Fcons(Qfg, make_color_string(pac)), part);
120
121 pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_BACKGROUND);
122 if (pac != NULL)
123 part = Fcons(Fcons(Qbg, make_color_string(pac)), part);
124
125 part = Fnreverse(part);
126 list = Fcons(part, list);
127 } while (pango_attr_iterator_next(iter));
128
129 list = Fnreverse(list);
130 pgtk_enqueue_preedit(f, list);
131
132 g_free(str);
133 pango_attr_list_unref(attrs);
134}
135
136static void im_context_preedit_end_cb(GtkIMContext *imc, gpointer user_data)
137{
138 struct pgtk_display_info *dpyinfo = user_data;
139 struct frame *f = dpyinfo->im.focused_frame;
140
141 if (dpyinfo->im.context == NULL)
142 return;
143 if (f == NULL)
144 return;
145
146 pgtk_enqueue_preedit(f, Qnil);
147}
148
149static void im_context_preedit_start_cb(GtkIMContext *imc, gpointer user_data)
150{
151}
152
153void pgtk_im_focus_in(struct frame *f)
154{
155 struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
156 if (dpyinfo->im.context != NULL) {
157 gtk_im_context_reset (dpyinfo->im.context);
158 gtk_im_context_set_client_window (dpyinfo->im.context, gtk_widget_get_window (FRAME_GTK_WIDGET (f)));
159 gtk_im_context_focus_in (dpyinfo->im.context);
160 }
161 dpyinfo->im.focused_frame = f;
162}
163
164void pgtk_im_focus_out(struct frame *f)
165{
166 struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
167 if (dpyinfo->im.focused_frame == f) {
168 if (dpyinfo->im.context != NULL) {
169 gtk_im_context_reset (dpyinfo->im.context);
170 gtk_im_context_focus_out (dpyinfo->im.context);
171 gtk_im_context_set_client_window (dpyinfo->im.context, NULL);
172 }
173 dpyinfo->im.focused_frame = NULL;
174 }
175}
176
177bool pgtk_im_filter_keypress(struct frame *f, GdkEventKey *ev)
178{
179 struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
180 if (dpyinfo->im.context != NULL) {
181 if (gtk_im_context_filter_keypress (dpyinfo->im.context, ev))
182 return true;
183 }
184 return false;
185}
186
187void pgtk_im_init(struct pgtk_display_info *dpyinfo)
188{
189 dpyinfo->im.context = NULL;
190}
191
192void pgtk_im_finish(struct pgtk_display_info *dpyinfo)
193{
194 if (dpyinfo->im.context != NULL)
195 g_object_unref(dpyinfo->im.context);
196 dpyinfo->im.context = NULL;
197}
198
199DEFUN ("pgtk-use-im-context", Fpgtk_use_im_context, Spgtk_use_im_context,
200 1, 2, 0,
201 doc: /* Set whether use Gtk's im context. */)
202 (Lisp_Object use_p, Lisp_Object terminal)
203{
204 struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal);
205
206 if (NILP(use_p)) {
207 if (dpyinfo->im.context != NULL) {
208 gtk_im_context_reset (dpyinfo->im.context);
209 gtk_im_context_focus_out (dpyinfo->im.context);
210 gtk_im_context_set_client_window (dpyinfo->im.context, NULL);
211
212 g_object_unref(dpyinfo->im.context);
213 dpyinfo->im.context = NULL;
214 }
215 } else {
216 if (dpyinfo->im.context == NULL) {
217 dpyinfo->im.context = gtk_im_multicontext_new();
218 g_signal_connect(dpyinfo->im.context, "commit", G_CALLBACK(im_context_commit_cb), dpyinfo);
219 g_signal_connect(dpyinfo->im.context, "retrieve-surrounding", G_CALLBACK(im_context_retrieve_surrounding_cb), dpyinfo);
220 g_signal_connect(dpyinfo->im.context, "delete-surrounding", G_CALLBACK(im_context_delete_surrounding_cb), dpyinfo);
221 g_signal_connect(dpyinfo->im.context, "preedit-changed", G_CALLBACK(im_context_preedit_changed_cb), dpyinfo);
222 g_signal_connect(dpyinfo->im.context, "preedit-end", G_CALLBACK(im_context_preedit_end_cb), dpyinfo);
223 g_signal_connect(dpyinfo->im.context, "preedit-start", G_CALLBACK(im_context_preedit_start_cb), dpyinfo);
224 gtk_im_context_set_use_preedit (dpyinfo->im.context, TRUE);
225
226 if (dpyinfo->im.focused_frame)
227 pgtk_im_focus_in(dpyinfo->im.focused_frame);
228 }
229 }
230
231 return Qnil;
232}
233
234void
235syms_of_pgtkim (void)
236{
237 defsubr (&Spgtk_use_im_context);
238
239 DEFSYM (Qpgtk_refresh_preedit, "pgtk-refresh-preedit");
240 DEFSYM (Qul, "ul");
241 DEFSYM (Qfg, "fg");
242 DEFSYM (Qbg, "bg");
243}
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index fab6e4eed98..67ff3786332 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -188,6 +188,7 @@ x_free_frame_resources (struct frame *f)
188 CLEAR_IF_EQ(last_mouse_frame); 188 CLEAR_IF_EQ(last_mouse_frame);
189 CLEAR_IF_EQ(last_mouse_motion_frame); 189 CLEAR_IF_EQ(last_mouse_motion_frame);
190 CLEAR_IF_EQ(last_mouse_glyph_frame); 190 CLEAR_IF_EQ(last_mouse_glyph_frame);
191 CLEAR_IF_EQ(im.focused_frame);
191 192
192#undef CLEAR_IF_EQ 193#undef CLEAR_IF_EQ
193 194
@@ -4282,6 +4283,8 @@ pgtk_delete_terminal (struct terminal *terminal)
4282 4283
4283 block_input (); 4284 block_input ();
4284 4285
4286 pgtk_im_finish (dpyinfo);
4287
4285 /* Normally, the display is available... */ 4288 /* Normally, the display is available... */
4286 if (dpyinfo->gdpy) 4289 if (dpyinfo->gdpy)
4287 { 4290 {
@@ -4952,6 +4955,45 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state)
4952#define IsKeypadKey(keysym) (0xff80 <= (keysym) && (keysym) < 0xffbe) 4955#define IsKeypadKey(keysym) (0xff80 <= (keysym) && (keysym) < 0xffbe)
4953#define IsFunctionKey(keysym) (0xffbe <= (keysym) && (keysym) < 0xffe1) 4956#define IsFunctionKey(keysym) (0xffbe <= (keysym) && (keysym) < 0xffe1)
4954 4957
4958void
4959pgtk_enqueue_string(struct frame *f, gchar *str)
4960{
4961 gunichar *ustr;
4962
4963 ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL);
4964 if (ustr == NULL)
4965 return;
4966 for ( ; *ustr != 0; ustr++) {
4967 union buffered_input_event inev;
4968 Lisp_Object c = make_fixnum (*ustr);
4969 EVENT_INIT (inev.ie);
4970 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
4971 ? ASCII_KEYSTROKE_EVENT
4972 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
4973 inev.ie.arg = Qnil;
4974 inev.ie.code = XFIXNAT (c);
4975 XSETFRAME (inev.ie.frame_or_window, f);
4976 inev.ie.modifiers = 0;
4977 inev.ie.timestamp = 0;
4978 evq_enqueue (&inev);
4979 }
4980
4981}
4982
4983void
4984pgtk_enqueue_preedit(struct frame *f, Lisp_Object preedit)
4985{
4986 union buffered_input_event inev;
4987 EVENT_INIT (inev.ie);
4988 inev.ie.kind = PGTK_PREEDIT_TEXT_EVENT;
4989 inev.ie.arg = preedit;
4990 inev.ie.code = 0;
4991 XSETFRAME (inev.ie.frame_or_window, f);
4992 inev.ie.modifiers = 0;
4993 inev.ie.timestamp = 0;
4994 evq_enqueue (&inev);
4995}
4996
4955static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) 4997static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data)
4956{ 4998{
4957 struct coding_system coding; 4999 struct coding_system coding;
@@ -4978,6 +5020,11 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us
4978 hlinfo->mouse_face_hidden = true; 5020 hlinfo->mouse_face_hidden = true;
4979 } 5021 }
4980 5022
5023 if (f != 0) {
5024 if (pgtk_im_filter_keypress (f, &event->key))
5025 return TRUE;
5026 }
5027
4981 if (f != 0) 5028 if (f != 0)
4982 { 5029 {
4983 guint keysym, orig_keysym; 5030 guint keysym, orig_keysym;
@@ -5462,6 +5509,9 @@ focus_in_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data)
5462 FRAME_DISPLAY_INFO(frame), frame, &inev); 5509 FRAME_DISPLAY_INFO(frame), frame, &inev);
5463 if (inev.ie.kind != NO_EVENT) 5510 if (inev.ie.kind != NO_EVENT)
5464 evq_enqueue (&inev); 5511 evq_enqueue (&inev);
5512
5513 pgtk_im_focus_in (frame);
5514
5465 return TRUE; 5515 return TRUE;
5466} 5516}
5467 5517
@@ -5483,6 +5533,9 @@ focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data)
5483 FRAME_DISPLAY_INFO(frame), frame, &inev); 5533 FRAME_DISPLAY_INFO(frame), frame, &inev);
5484 if (inev.ie.kind != NO_EVENT) 5534 if (inev.ie.kind != NO_EVENT)
5485 evq_enqueue(&inev); 5535 evq_enqueue(&inev);
5536
5537 pgtk_im_focus_out (frame);
5538
5486 return TRUE; 5539 return TRUE;
5487} 5540}
5488 5541
@@ -6219,6 +6272,8 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
6219 6272
6220 pgtk_selection_init(); 6273 pgtk_selection_init();
6221 6274
6275 pgtk_im_init (dpyinfo);
6276
6222 unblock_input (); 6277 unblock_input ();
6223 6278
6224 return dpyinfo; 6279 return dpyinfo;
diff --git a/src/pgtkterm.h b/src/pgtkterm.h
index a2ba627425c..694a85bac2e 100644
--- a/src/pgtkterm.h
+++ b/src/pgtkterm.h
@@ -226,6 +226,14 @@ struct pgtk_display_info
226 226
227 /* Modifier masks in gdk */ 227 /* Modifier masks in gdk */
228 int meta_mod_mask, alt_mod_mask; 228 int meta_mod_mask, alt_mod_mask;
229
230 /* whether to use Gtk's IM context. */
231
232 /* input method */
233 struct {
234 GtkIMContext *context;
235 struct frame *focused_frame;
236 } im;
229}; 237};
230 238
231/* This is a chain of structures for all the PGTK displays currently in use. */ 239/* This is a chain of structures for all the PGTK displays currently in use. */
@@ -579,6 +587,7 @@ extern void syms_of_pgtkterm (void);
579extern void syms_of_pgtkfns (void); 587extern void syms_of_pgtkfns (void);
580extern void syms_of_pgtkmenu (void); 588extern void syms_of_pgtkmenu (void);
581extern void syms_of_pgtkselect (void); 589extern void syms_of_pgtkselect (void);
590extern void syms_of_pgtkim (void);
582 591
583/* Implemented in pgtkselect. */ 592/* Implemented in pgtkselect. */
584extern void nxatoms_of_pgtkselect (void); 593extern void nxatoms_of_pgtkselect (void);
@@ -602,4 +611,14 @@ extern void pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo);
602 611
603extern void x_change_tab_bar_height (struct frame *, int); 612extern void x_change_tab_bar_height (struct frame *, int);
604 613
614extern struct pgtk_display_info *check_pgtk_display_info (Lisp_Object object);
615
616extern void pgtk_enqueue_string(struct frame *f, gchar *str);
617extern void pgtk_enqueue_preedit(struct frame *f, Lisp_Object image_data);
618extern void pgtk_im_focus_in(struct frame *f);
619extern void pgtk_im_focus_out(struct frame *f);
620extern bool pgtk_im_filter_keypress(struct frame *f, GdkEventKey *ev);
621extern void pgtk_im_init(struct pgtk_display_info *dpyinfo);
622extern void pgtk_im_finish(struct pgtk_display_info *dpyinfo);
623
605#endif /* HAVE_PGTK */ 624#endif /* HAVE_PGTK */
diff --git a/src/termhooks.h b/src/termhooks.h
index 4403d518ff0..c28c3fbbd02 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -264,6 +264,10 @@ enum event_kind
264 , FILE_NOTIFY_EVENT 264 , FILE_NOTIFY_EVENT
265#endif 265#endif
266 266
267#ifdef HAVE_PGTK
268 /* Pre-edit text was changed. */
269 , PGTK_PREEDIT_TEXT_EVENT
270#endif
267}; 271};
268 272
269/* Bit width of an enum event_kind tag at the start of structs and unions. */ 273/* Bit width of an enum event_kind tag at the start of structs and unions. */