NetSurf
selectmenu.c
Go to the documentation of this file.
1/*
2 * Copyright 2008 - 2011 Chris Young <chris@unsatisfactorysoftware.co.uk>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef __amigaos4__
20
21#include <stdbool.h>
22#include <proto/exec.h>
23#include <proto/intuition.h>
24#include <proto/popupmenu.h>
25#include <proto/utility.h>
26#include <reaction/reaction_macros.h>
27
28#include "utils/errors.h"
29#include "utils/log.h"
30#include "utils/messages.h"
31#include "netsurf/form.h"
32#include "netsurf/mouse.h"
33
34#include "amiga/gui.h"
35#include "amiga/selectmenu.h"
36#include "amiga/theme.h"
37#include "amiga/utf8.h"
38
39/* Maximum number of items for a popupmenu.class select menu.
40 * 50 is about the limit for my screen, and popupmenu doesn't scroll.
41 * We may need to calculate a value for this based on screen/font size.
42 *
43 * Additional entries will be added to a "More" menu...
44 */
45#define AMI_SELECTMENU_PAGE_MAX 40
46
47/* ...limited to the number of menus defined here... */
48#define AMI_SELECTMENU_MENU_MAX 10
49
50/* ...and resulting in this total number of entries. */
51#define AMI_SELECTMENU_MAX (AMI_SELECTMENU_PAGE_MAX * AMI_SELECTMENU_MENU_MAX)
52
53
54/** Exported interface documented in selectmenu.h **/
56{
57 struct Library *PopupMenuBase;
58 BOOL popupmenu_lib_ok = FALSE;
59
60 if((PopupMenuBase = OpenLibrary("popupmenu.library", 53))) {
61 NSLOG(netsurf, INFO, "popupmenu.library v%d.%d",
62 PopupMenuBase->lib_Version, PopupMenuBase->lib_Revision);
63 if(LIB_IS_AT_LEAST((struct Library *)PopupMenuBase, 53, 11))
64 popupmenu_lib_ok = TRUE;
65 CloseLibrary(PopupMenuBase);
66 }
67
68 return popupmenu_lib_ok;
69}
70
71HOOKF(uint32, ami_popup_hook, Object *, item, APTR)
72{
73 uint32 itemid = 0;
74 struct form_control *control = hook->h_Data;
75
76 if(GetAttr(PMIA_ID, item, &itemid)) {
77 form_select_process_selection(control, itemid);
78 }
79
80 return itemid;
81}
82
84 struct form_control *control)
85{
86 struct Library *PopupMenuBase = NULL;
87 struct PopupMenuIFace *IPopupMenu = NULL;
88 struct Hook selectmenuhook;
89 Object *selectmenuobj;
90 Object *smenu = NULL;
91 Object *currentmenu;
92 Object *submenu = NULL;
93 char *selectmenu_item[AMI_SELECTMENU_MAX];
94 char *more_label;
95 struct form_option *opt = form_select_get_option(control, 0);
96 int i = 0;
97 int n = 0;
98
99 if(ami_selectmenu_is_safe() == FALSE) return;
100
101 if((PopupMenuBase = OpenLibrary("popupmenu.class", 0))) {
102 IPopupMenu = (struct PopupMenuIFace *)GetInterface(PopupMenuBase, "main", 1, NULL);
103 }
104
105 if(IPopupMenu == NULL) return;
106
107 ClearMem(selectmenu_item, AMI_SELECTMENU_MAX * 4);
108 more_label = ami_utf8_easy(messages_get("More"));
109
110 selectmenuhook.h_Entry = ami_popup_hook;
111 selectmenuhook.h_SubEntry = NULL;
112 selectmenuhook.h_Data = control;
113
114 selectmenuobj = PMMENU(form_control_get_name(control)),
115 PMA_MenuHandler, &selectmenuhook, End;
116
117 currentmenu = selectmenuobj;
118
119 while(opt) {
120 selectmenu_item[i] = ami_utf8_easy(opt->text);
121
122 IDoMethod(currentmenu, PM_INSERT,
123 NewObject(POPUPMENU_GetItemClass(), NULL,
124 PMIA_Title, (ULONG)selectmenu_item[i],
125 PMIA_ID, i,
126 PMIA_CheckIt, TRUE,
127 PMIA_Checked, opt->selected,
128 TAG_DONE),
129 ~0);
130
131 opt = opt->next;
132 i++;
133 n++;
134
135 if(n == AMI_SELECTMENU_PAGE_MAX) {
136 if(submenu != NULL) {
137 /* attach the previous submenu */
138 IDoMethod(smenu, PM_INSERT,
139 NewObject(NULL, "popupmenuitem.class",
140 PMIA_Title, more_label,
141 PMIA_CheckIt, TRUE,
142 PMIA_SubMenu, submenu,
143 TAG_DONE),
144 ~0);
145 }
146
147 submenu = NewObject(NULL, "popupmenu.class", TAG_DONE);
148 smenu = currentmenu;
149 currentmenu = submenu;
150 n = 0;
151 }
152
153 if(i >= AMI_SELECTMENU_MAX) break;
154 }
155
156 if((submenu != NULL) && (n != 0)) {
157 /* attach the previous submenu */
158 IDoMethod(smenu, PM_INSERT,
159 NewObject(NULL, "popupmenuitem.class",
160 PMIA_Title, more_label,
161 PMIA_CheckIt, TRUE,
162 PMIA_SubMenu, submenu,
163 TAG_DONE),
164 ~0);
165 }
166
167 ami_set_pointer(ami_gui_get_gui_window_2(g), GUI_POINTER_DEFAULT, false); // Clear the menu-style pointer
168
169 IDoMethod(selectmenuobj, PM_OPEN, ami_gui_get_window(g));
170
171 /* PM_OPEN is blocking, so dispose menu immediately... */
172 if(selectmenuobj) DisposeObject(selectmenuobj);
173
174 /* ...and get rid of popupmenu.class ASAP */
175 if(IPopupMenu) DropInterface((struct Interface *)IPopupMenu);
176 if(PopupMenuBase) CloseLibrary(PopupMenuBase);
177
178 /* Free the menu labels */
179 if(more_label) ami_utf8_free(more_label);
180 for(i = 0; i < AMI_SELECTMENU_MAX; i++) {
181 if(selectmenu_item[i] != NULL) {
182 ami_utf8_free(selectmenu_item[i]);
183 selectmenu_item[i] = NULL;
184 }
185 }
186}
187
188#else
189#include "amiga/selectmenu.h"
191{
192}
193
195{
196 return FALSE;
197}
198#endif
199
struct Window * ami_gui_get_window(struct gui_window *gw)
Get window from gui_window.
Definition: gui.c:576
void ami_set_pointer(struct gui_window_2 *gwin, gui_pointer_shape shape, bool update)
Definition: gui.c:688
struct gui_window_2 * ami_gui_get_gui_window_2(struct gui_window *gw)
Get gui_window_2 from gui_window.
Definition: gui.c:437
#define HOOKF(ret, func, type, ptr, msgtype)
Definition: gui.h:38
Error codes.
Form handling public interface.
char * form_control_get_name(struct form_control *control)
Get a form control name.
Definition: form.c:1858
struct form_option * form_select_get_option(struct form_control *control, int item)
get a form select menus option.
Definition: form.c:1844
nserror form_select_process_selection(struct form_control *control, int item)
Process a selection from a form select menu.
Definition: form.c:1834
void ami_utf8_free(char *ptr)
Definition: utf8.c:104
char * ami_utf8_easy(const char *string)
Definition: utf8.c:109
Core mouse and pointer states.
@ GUI_POINTER_DEFAULT
Definition: mouse.h:90
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
APTR NewObject(struct IClass *classPtr, CONST_STRPTR classID, ULONG tagList,...)
Definition: os3support.c:434
#define LIB_IS_AT_LEAST(B, V, R)
Definition: os3support.h:55
#define IDoMethod
Definition: os3support.h:169
uint32_t uint32
Definition: os3support.h:184
BOOL ami_selectmenu_is_safe()
Opens popupmenu.library to check the version.
Definition: selectmenu.c:194
void gui_create_form_select_menu(struct gui_window *g, struct form_control *control)
Definition: selectmenu.c:190
Form control.
Definition: form_internal.h:73
Option in a select.
Definition: form.h:33
struct form_option * next
Definition: form.h:39
bool selected
Definition: form.h:35
char * text
NUL terminated.
Definition: form.h:38
first entry in window list
Definition: gui.c:296