Fixed some problems in 0.60.0
[wmaker-crm.git] / wmlib / menu.c
blob9e2255847924a28681be481744746ce0a014ab27
1 /* menu.c - menu interface functions
2 *
3 * WMlib - WindowMaker application programming interface
4 *
5 * Copyright (C) 1997 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.
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.
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.
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
28 #include "WMaker.h"
29 #include "app.h"
30 #include "menu.h"
33 WMMenu*
34 WMMenuCreate(WMAppContext *app, char *title)
36 wmMenu *menu;
38 if (strlen(title)>255)
39 return NULL;
41 menu = malloc(sizeof(wmMenu));
42 if (!menu)
43 return NULL;
45 menu->appcontext = app;
46 menu->parent = NULL;
47 menu->title = title;
48 menu->entries = NULL;
49 menu->first = NULL;
51 menu->realized = False;
52 menu->code = app->last_menu_tag++;
54 menu->entryline = malloc(strlen(title)+32);
55 menu->entryline2 = malloc(32);
56 if (!menu->entryline || !menu->entryline2) {
57 if (menu->entryline)
58 free(menu->entryline);
59 free(menu);
60 return NULL;
62 sprintf(menu->entryline, "%i %i %s", wmBeginMenu, menu->code, title);
63 sprintf(menu->entryline2, "%i %i", wmEndMenu, menu->code);
64 return menu;
68 int
69 WMMenuAddItem(WMMenu *menu, char *text, WMMenuAction action,
70 void *clientData, WMFreeFunction freedata, char *rtext)
72 wmMenuEntry *entry;
74 /* max size of right side text */
75 if (rtext && strlen(rtext)>4)
76 return -1;
78 /* max size of menu text */
79 if (strlen(text)>255)
80 return -1;
82 entry = malloc(sizeof(wmMenuEntry));
83 if (!entry)
84 return -1;
86 entry->entryline = malloc(strlen(text)+100);
87 if (!entry->entryline) {
88 free(menu);
89 return -1;
92 if (menu->entries)
93 entry->order = menu->entries->order + 1;
94 else {
95 entry->order = 0;
96 menu->first = entry;
98 entry->next = NULL;
99 entry->prev = menu->entries;
100 if (menu->entries)
101 menu->entries->next = entry;
102 menu->entries = entry;
104 entry->menu = menu;
105 entry->text = text;
106 entry->shortcut = rtext;
107 entry->callback = action;
108 entry->clientData = clientData;
109 entry->free = freedata;
110 entry->tag = menu->appcontext->last_menu_tag++;
111 entry->cascade = NULL;
112 entry->enabled = True;
115 if (!rtext)
116 sprintf(entry->entryline, "%i %i %i %i %s", wmNormalItem,
117 menu->code, entry->tag, True, text);
118 else
119 sprintf(entry->entryline, "%i %i %i %i %s %s", wmDoubleItem,
120 menu->code, entry->tag, True, rtext, text);
121 return entry->tag;
127 WMMenuAddSubmenu(WMMenu *menu, char *text, WMMenu *submenu)
129 wmMenuEntry *entry;
131 /* max size of menu text */
132 if (strlen(text)>255)
133 return -1;
135 entry = malloc(sizeof(wmMenuEntry));
136 if (!entry)
137 return -1;
139 entry->entryline = malloc(strlen(text)+100);
140 if (!entry->entryline) {
141 free(menu);
142 return -1;
145 if (menu->entries)
146 entry->order = menu->entries->order + 1;
147 else {
148 entry->order = 0;
149 menu->first = entry;
151 entry->next = NULL;
152 entry->prev = menu->entries;
153 if (menu->entries)
154 menu->entries->next = entry;
155 menu->entries = entry;
156 entry->menu = menu;
157 entry->text = text;
158 entry->shortcut = NULL;
159 entry->callback = NULL;
160 entry->clientData = NULL;
161 entry->tag = menu->appcontext->last_menu_tag++;
162 entry->cascade = submenu;
163 entry->enabled = True;
165 sprintf(entry->entryline, "%i %i %i %i %i %s", wmSubmenuItem,
166 menu->code, entry->tag, True, submenu->code, text);
167 return entry->tag;
171 static int
172 countItems(WMMenu *menu)
174 wmMenuEntry *entry = menu->first;
175 int c;
177 c = 1;
178 while (entry) {
179 c++;
180 if (entry->cascade) {
181 c += countItems(entry->cascade);
183 entry = entry->next;
185 c++;
186 return c;
190 static void
191 addItems(char **slist, int *index, WMMenu *menu)
193 wmMenuEntry *entry = menu->first;
195 slist[(*index)++] = menu->entryline;
196 while (entry) {
197 slist[(*index)++] = entry->entryline;
198 if (entry->cascade) {
199 addItems(slist, index, entry->cascade);
201 entry = entry->next;
203 slist[(*index)++] = menu->entryline2;
207 static Atom
208 getatom(Display *dpy)
210 static Atom atom=0;
212 if (atom==0) {
213 atom = XInternAtom(dpy, WMMENU_PROPNAME, False);
215 return atom;
218 int
219 WMRealizeMenus(WMAppContext *app)
221 int i, count;
222 char **slist;
223 XTextProperty text_prop;
225 if (!app->main_menu)
226 return False;
228 /* first count how many menu items there are */
229 count = countItems(app->main_menu);
230 if (count==0)
231 return True;
233 count++;
234 slist = malloc(count*sizeof(char*));
235 if (!slist) {
236 return False;
239 slist[0] = "WMMenu 0";
240 i = 1;
241 addItems(slist, &i, app->main_menu);
243 if (!XStringListToTextProperty(slist, i, &text_prop)) {
244 free(slist);
245 return False;
247 free(slist);
248 XSetTextProperty(app->dpy, app->main_window, &text_prop,
249 getatom(app->dpy));
251 XFree(text_prop.value);
253 return True;