Change to the linux kernel coding style
[wmaker-crm.git] / wmlib / menu.c
1 /* menu.c - menu interface functions
2 *
3 * WMlib - WindowMaker application programming interface
4 *
5 * Copyright (C) 1997-2003 Alfredo K. Kojima
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library 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 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27
28 #include "WMaker.h"
29 #include "app.h"
30 #include "menu.h"
31
32 WMMenu *WMMenuCreate(WMAppContext * app, char *title)
33 {
34 wmMenu *menu;
35
36 if (strlen(title) > 255)
37 return NULL;
38
39 menu = malloc(sizeof(wmMenu));
40 if (!menu)
41 return NULL;
42
43 menu->appcontext = app;
44 menu->parent = NULL;
45 menu->title = title;
46 menu->entries = NULL;
47 menu->first = NULL;
48
49 menu->realized = False;
50 menu->code = app->last_menu_tag++;
51
52 menu->entryline = malloc(strlen(title) + 32);
53 menu->entryline2 = malloc(32);
54 if (!menu->entryline || !menu->entryline2) {
55 if (menu->entryline)
56 free(menu->entryline);
57 free(menu);
58 return NULL;
59 }
60 sprintf(menu->entryline, "%i %i %s", wmBeginMenu, menu->code, title);
61 sprintf(menu->entryline2, "%i %i", wmEndMenu, menu->code);
62 return menu;
63 }
64
65 int
66 WMMenuAddItem(WMMenu * menu, char *text, WMMenuAction action,
67 void *clientData, WMFreeFunction freedata, char *rtext)
68 {
69 wmMenuEntry *entry;
70
71 /* max size of right side text */
72 if (rtext && strlen(rtext) > 4)
73 return -1;
74
75 /* max size of menu text */
76 if (strlen(text) > 255)
77 return -1;
78
79 entry = malloc(sizeof(wmMenuEntry));
80 if (!entry)
81 return -1;
82
83 entry->entryline = malloc(strlen(text) + 100);
84 if (!entry->entryline) {
85 free(menu);
86 return -1;
87 }
88
89 if (menu->entries)
90 entry->order = menu->entries->order + 1;
91 else {
92 entry->order = 0;
93 menu->first = entry;
94 }
95 entry->next = NULL;
96 entry->prev = menu->entries;
97 if (menu->entries)
98 menu->entries->next = entry;
99 menu->entries = entry;
100
101 entry->menu = menu;
102 entry->text = text;
103 entry->shortcut = rtext;
104 entry->callback = action;
105 entry->clientData = clientData;
106 entry->free = freedata;
107 entry->tag = menu->appcontext->last_menu_tag++;
108 entry->cascade = NULL;
109 entry->enabled = True;
110
111 if (!rtext)
112 sprintf(entry->entryline, "%i %i %i %i %s", wmNormalItem, menu->code, entry->tag, True, text);
113 else
114 sprintf(entry->entryline, "%i %i %i %i %s %s", wmDoubleItem,
115 menu->code, entry->tag, True, rtext, text);
116 return entry->tag;
117 }
118
119 int WMMenuAddSubmenu(WMMenu * menu, char *text, WMMenu * submenu)
120 {
121 wmMenuEntry *entry;
122
123 /* max size of menu text */
124 if (strlen(text) > 255)
125 return -1;
126
127 entry = malloc(sizeof(wmMenuEntry));
128 if (!entry)
129 return -1;
130
131 entry->entryline = malloc(strlen(text) + 100);
132 if (!entry->entryline) {
133 free(menu);
134 return -1;
135 }
136
137 if (menu->entries)
138 entry->order = menu->entries->order + 1;
139 else {
140 entry->order = 0;
141 menu->first = entry;
142 }
143 entry->next = NULL;
144 entry->prev = menu->entries;
145 if (menu->entries)
146 menu->entries->next = entry;
147 menu->entries = entry;
148 entry->menu = menu;
149 entry->text = text;
150 entry->shortcut = NULL;
151 entry->callback = NULL;
152 entry->clientData = NULL;
153 entry->tag = menu->appcontext->last_menu_tag++;
154 entry->cascade = submenu;
155 entry->enabled = True;
156
157 sprintf(entry->entryline, "%i %i %i %i %i %s", wmSubmenuItem,
158 menu->code, entry->tag, True, submenu->code, text);
159 return entry->tag;
160 }
161
162 static int countItems(WMMenu * menu)
163 {
164 wmMenuEntry *entry = menu->first;
165 int c;
166
167 c = 1;
168 while (entry) {
169 c++;
170 if (entry->cascade) {
171 c += countItems(entry->cascade);
172 }
173 entry = entry->next;
174 }
175 c++;
176 return c;
177 }
178
179 static void addItems(char **slist, int *index, WMMenu * menu)
180 {
181 wmMenuEntry *entry = menu->first;
182
183 slist[(*index)++] = menu->entryline;
184 while (entry) {
185 slist[(*index)++] = entry->entryline;
186 if (entry->cascade) {
187 addItems(slist, index, entry->cascade);
188 }
189 entry = entry->next;
190 }
191 slist[(*index)++] = menu->entryline2;
192 }
193
194 static Atom getatom(Display * dpy)
195 {
196 static Atom atom = 0;
197
198 if (atom == 0) {
199 atom = XInternAtom(dpy, WMMENU_PROPNAME, False);
200 }
201 return atom;
202 }
203
204 int WMRealizeMenus(WMAppContext * app)
205 {
206 int i, count;
207 char **slist;
208 XTextProperty text_prop;
209
210 if (!app->main_menu)
211 return False;
212
213 /* first count how many menu items there are */
214 count = countItems(app->main_menu);
215 if (count == 0)
216 return True;
217
218 count++;
219 slist = malloc(count * sizeof(char *));
220 if (!slist) {
221 return False;
222 }
223
224 slist[0] = "WMMenu 0";
225 i = 1;
226 addItems(slist, &i, app->main_menu);
227
228 if (!XStringListToTextProperty(slist, i, &text_prop)) {
229 free(slist);
230 return False;
231 }
232 free(slist);
233 XSetTextProperty(app->dpy, app->main_window, &text_prop, getatom(app->dpy));
234
235 XFree(text_prop.value);
236
237 return True;
238 }