1c2c66affSColin Finck /*
2c2c66affSColin Finck * Copyright (c) 2011 Lucas Fialho Zawacki
3c2c66affSColin Finck *
4c2c66affSColin Finck * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck * License as published by the Free Software Foundation; either
7c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck *
9c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12c2c66affSColin Finck * Lesser General Public License for more details.
13c2c66affSColin Finck *
14c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck */
18c2c66affSColin Finck
197016dd6dSAmine Khaldi #define NONAMELESSUNION
207016dd6dSAmine Khaldi
21*41c8c312SAmine Khaldi
227016dd6dSAmine Khaldi #include "wine/unicode.h"
237016dd6dSAmine Khaldi #include "objbase.h"
24c2c66affSColin Finck #include "dinput_private.h"
257016dd6dSAmine Khaldi #include "device_private.h"
26c2c66affSColin Finck #include "resource.h"
27c2c66affSColin Finck
28*41c8c312SAmine Khaldi #include "wine/heap.h"
29*41c8c312SAmine Khaldi
30c2c66affSColin Finck typedef struct {
31c2c66affSColin Finck int nobjects;
32c2c66affSColin Finck IDirectInputDevice8W *lpdid;
33c2c66affSColin Finck DIDEVICEINSTANCEW ddi;
34c2c66affSColin Finck DIDEVICEOBJECTINSTANCEW ddo[256];
35*41c8c312SAmine Khaldi /* ActionFormat for every user.
36*41c8c312SAmine Khaldi * In same order as ConfigureDevicesData usernames */
37*41c8c312SAmine Khaldi DIACTIONFORMATW *user_afs;
38c2c66affSColin Finck } DeviceData;
39c2c66affSColin Finck
40c2c66affSColin Finck typedef struct {
41c2c66affSColin Finck int ndevices;
42c2c66affSColin Finck DeviceData *devices;
43c2c66affSColin Finck } DIDevicesData;
44c2c66affSColin Finck
45c2c66affSColin Finck typedef struct {
46c2c66affSColin Finck IDirectInput8W *lpDI;
47c2c66affSColin Finck LPDIACTIONFORMATW original_lpdiaf;
48c2c66affSColin Finck DIDevicesData devices_data;
49c2c66affSColin Finck int display_only;
50*41c8c312SAmine Khaldi int nusernames;
51*41c8c312SAmine Khaldi WCHAR **usernames;
52c2c66affSColin Finck } ConfigureDevicesData;
53c2c66affSColin Finck
54c2c66affSColin Finck /*
55c2c66affSColin Finck * Enumeration callback functions
56c2c66affSColin Finck */
collect_objects(LPCDIDEVICEOBJECTINSTANCEW lpddo,LPVOID pvRef)57c2c66affSColin Finck static BOOL CALLBACK collect_objects(LPCDIDEVICEOBJECTINSTANCEW lpddo, LPVOID pvRef)
58c2c66affSColin Finck {
59c2c66affSColin Finck DeviceData *data = (DeviceData*) pvRef;
60c2c66affSColin Finck
61c2c66affSColin Finck data->ddo[data->nobjects] = *lpddo;
62c2c66affSColin Finck
63c2c66affSColin Finck data->nobjects++;
64c2c66affSColin Finck return DIENUM_CONTINUE;
65c2c66affSColin Finck }
66c2c66affSColin Finck
collect_devices(LPCDIDEVICEINSTANCEW lpddi,IDirectInputDevice8W * lpdid,DWORD dwFlags,DWORD dwRemaining,LPVOID pvRef)67c2c66affSColin Finck static BOOL CALLBACK collect_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
68c2c66affSColin Finck {
69*41c8c312SAmine Khaldi ConfigureDevicesData *data = (ConfigureDevicesData*) pvRef;
70*41c8c312SAmine Khaldi DeviceData *device;
71*41c8c312SAmine Khaldi int i, j;
72c2c66affSColin Finck
73c2c66affSColin Finck IDirectInputDevice_AddRef(lpdid);
74c2c66affSColin Finck
75*41c8c312SAmine Khaldi /* alloc array for devices if this is our first device */
76*41c8c312SAmine Khaldi if (!data->devices_data.ndevices)
77*41c8c312SAmine Khaldi data->devices_data.devices = HeapAlloc(GetProcessHeap(), 0, sizeof(DeviceData) * (dwRemaining + 1));
78*41c8c312SAmine Khaldi device = &data->devices_data.devices[data->devices_data.ndevices];
79*41c8c312SAmine Khaldi device->lpdid = lpdid;
80*41c8c312SAmine Khaldi device->ddi = *lpddi;
81*41c8c312SAmine Khaldi
82c2c66affSColin Finck device->nobjects = 0;
83c2c66affSColin Finck IDirectInputDevice_EnumObjects(lpdid, collect_objects, (LPVOID) device, DIDFT_ALL);
84c2c66affSColin Finck
85*41c8c312SAmine Khaldi device->user_afs = heap_alloc(sizeof(*device->user_afs) * data->nusernames);
86*41c8c312SAmine Khaldi memset(device->user_afs, 0, sizeof(*device->user_afs) * data->nusernames);
87*41c8c312SAmine Khaldi for (i = 0; i < data->nusernames; i++)
88*41c8c312SAmine Khaldi {
89*41c8c312SAmine Khaldi DIACTIONFORMATW *user_af = &device->user_afs[i];
90*41c8c312SAmine Khaldi user_af->dwNumActions = data->original_lpdiaf->dwNumActions;
91*41c8c312SAmine Khaldi user_af->guidActionMap = data->original_lpdiaf->guidActionMap;
92*41c8c312SAmine Khaldi user_af->rgoAction = heap_alloc(sizeof(DIACTIONW) * data->original_lpdiaf->dwNumActions);
93*41c8c312SAmine Khaldi memset(user_af->rgoAction, 0, sizeof(DIACTIONW) * data->original_lpdiaf->dwNumActions);
94*41c8c312SAmine Khaldi for (j = 0; j < user_af->dwNumActions; j++)
95*41c8c312SAmine Khaldi {
96*41c8c312SAmine Khaldi user_af->rgoAction[j].dwSemantic = data->original_lpdiaf->rgoAction[j].dwSemantic;
97*41c8c312SAmine Khaldi user_af->rgoAction[j].dwFlags = data->original_lpdiaf->rgoAction[j].dwFlags;
98*41c8c312SAmine Khaldi user_af->rgoAction[j].u.lptszActionName = data->original_lpdiaf->rgoAction[j].u.lptszActionName;
99*41c8c312SAmine Khaldi }
100*41c8c312SAmine Khaldi IDirectInputDevice8_BuildActionMap(lpdid, user_af, data->usernames[i], 0);
101*41c8c312SAmine Khaldi }
102*41c8c312SAmine Khaldi
103*41c8c312SAmine Khaldi data->devices_data.ndevices++;
104c2c66affSColin Finck return DIENUM_CONTINUE;
105c2c66affSColin Finck }
106c2c66affSColin Finck
107c2c66affSColin Finck /*
108c2c66affSColin Finck * Listview utility functions
109c2c66affSColin Finck */
init_listview_columns(HWND dialog)110c2c66affSColin Finck static void init_listview_columns(HWND dialog)
111c2c66affSColin Finck {
112c2c66affSColin Finck LVCOLUMNW listColumn;
113c2c66affSColin Finck RECT viewRect;
114c2c66affSColin Finck int width;
115c2c66affSColin Finck WCHAR column[MAX_PATH];
116c2c66affSColin Finck
117c2c66affSColin Finck GetClientRect(GetDlgItem(dialog, IDC_DEVICEOBJECTSLIST), &viewRect);
118c2c66affSColin Finck width = (viewRect.right - viewRect.left)/2;
119c2c66affSColin Finck
12098e62237SAmine Khaldi LoadStringW(DINPUT_instance, IDS_OBJECTCOLUMN, column, ARRAY_SIZE(column));
121c2c66affSColin Finck listColumn.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
122c2c66affSColin Finck listColumn.pszText = column;
123c2c66affSColin Finck listColumn.cchTextMax = lstrlenW(listColumn.pszText);
124c2c66affSColin Finck listColumn.cx = width;
125c2c66affSColin Finck
126c2c66affSColin Finck SendDlgItemMessageW (dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTCOLUMNW, 0, (LPARAM) &listColumn);
127c2c66affSColin Finck
12898e62237SAmine Khaldi LoadStringW(DINPUT_instance, IDS_ACTIONCOLUMN, column, ARRAY_SIZE(column));
129c2c66affSColin Finck listColumn.cx = width;
130c2c66affSColin Finck listColumn.pszText = column;
131c2c66affSColin Finck listColumn.cchTextMax = lstrlenW(listColumn.pszText);
132c2c66affSColin Finck
133c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTCOLUMNW, 1, (LPARAM) &listColumn);
134c2c66affSColin Finck }
135c2c66affSColin Finck
lv_get_cur_item(HWND dialog)136c2c66affSColin Finck static int lv_get_cur_item(HWND dialog)
137c2c66affSColin Finck {
138c2c66affSColin Finck return SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
139c2c66affSColin Finck }
140c2c66affSColin Finck
lv_get_item_data(HWND dialog,int index)141c2c66affSColin Finck static int lv_get_item_data(HWND dialog, int index)
142c2c66affSColin Finck {
143c2c66affSColin Finck LVITEMW item;
144c2c66affSColin Finck
145c2c66affSColin Finck if (index < 0) return -1;
146c2c66affSColin Finck
147c2c66affSColin Finck item.mask = LVIF_PARAM;
148c2c66affSColin Finck item.iItem = index;
149c2c66affSColin Finck item.iSubItem = 0;
150c2c66affSColin Finck
151c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_GETITEMW , 0, (LPARAM)&item);
152c2c66affSColin Finck
153c2c66affSColin Finck return item.lParam;
154c2c66affSColin Finck }
155c2c66affSColin Finck
lv_set_action(HWND dialog,int item,int action,LPDIACTIONFORMATW lpdiaf)156c2c66affSColin Finck static void lv_set_action(HWND dialog, int item, int action, LPDIACTIONFORMATW lpdiaf)
157c2c66affSColin Finck {
158c2c66affSColin Finck static const WCHAR no_action[] = {'-','\0'};
159c2c66affSColin Finck const WCHAR *action_text = no_action;
160c2c66affSColin Finck LVITEMW lvItem;
161c2c66affSColin Finck
162c2c66affSColin Finck if (item < 0) return;
163c2c66affSColin Finck
164c2c66affSColin Finck if (action != -1)
165c2c66affSColin Finck action_text = lpdiaf->rgoAction[action].u.lptszActionName;
166c2c66affSColin Finck
167c2c66affSColin Finck /* Keep the action and text in the listview item */
168c2c66affSColin Finck lvItem.iItem = item;
169c2c66affSColin Finck
170c2c66affSColin Finck lvItem.mask = LVIF_PARAM;
171c2c66affSColin Finck lvItem.iSubItem = 0;
172c2c66affSColin Finck lvItem.lParam = (LPARAM) action;
173c2c66affSColin Finck
174c2c66affSColin Finck /* Action index */
175c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_SETITEMW, 0, (LPARAM) &lvItem);
176c2c66affSColin Finck
177c2c66affSColin Finck lvItem.mask = LVIF_TEXT;
178c2c66affSColin Finck lvItem.iSubItem = 1;
179c2c66affSColin Finck lvItem.pszText = (WCHAR *)action_text;
180c2c66affSColin Finck lvItem.cchTextMax = lstrlenW(lvItem.pszText);
181c2c66affSColin Finck
182c2c66affSColin Finck /* Text */
183c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_SETITEMW, 0, (LPARAM) &lvItem);
184c2c66affSColin Finck }
185c2c66affSColin Finck
186c2c66affSColin Finck /*
187c2c66affSColin Finck * Utility functions
188c2c66affSColin Finck */
get_cur_device(HWND dialog)189c2c66affSColin Finck static DeviceData* get_cur_device(HWND dialog)
190c2c66affSColin Finck {
191c2c66affSColin Finck ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
192c2c66affSColin Finck int sel = SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_GETCURSEL, 0, 0);
193c2c66affSColin Finck return &data->devices_data.devices[sel];
194c2c66affSColin Finck }
195c2c66affSColin Finck
get_cur_lpdiaf(HWND dialog)196*41c8c312SAmine Khaldi static DIACTIONFORMATW *get_cur_lpdiaf(HWND dialog)
197c2c66affSColin Finck {
198c2c66affSColin Finck ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
199*41c8c312SAmine Khaldi int controller_sel = SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_GETCURSEL, 0, 0);
200*41c8c312SAmine Khaldi int player_sel = SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_GETCURSEL, 0, 0);
201*41c8c312SAmine Khaldi return &data->devices_data.devices[controller_sel].user_afs[player_sel];
202*41c8c312SAmine Khaldi }
203*41c8c312SAmine Khaldi
get_original_lpdiaf(HWND dialog)204*41c8c312SAmine Khaldi static DIACTIONFORMATW *get_original_lpdiaf(HWND dialog)
205*41c8c312SAmine Khaldi {
206*41c8c312SAmine Khaldi ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
207*41c8c312SAmine Khaldi return data->original_lpdiaf;
208c2c66affSColin Finck }
209c2c66affSColin Finck
dialog_display_only(HWND dialog)210c2c66affSColin Finck static int dialog_display_only(HWND dialog)
211c2c66affSColin Finck {
212c2c66affSColin Finck ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
213c2c66affSColin Finck return data->display_only;
214c2c66affSColin Finck }
215c2c66affSColin Finck
init_devices(HWND dialog,ConfigureDevicesData * data)216*41c8c312SAmine Khaldi static void init_devices(HWND dialog, ConfigureDevicesData *data)
217c2c66affSColin Finck {
218c2c66affSColin Finck int i;
219c2c66affSColin Finck
220c2c66affSColin Finck /* Collect and insert */
221*41c8c312SAmine Khaldi data->devices_data.ndevices = 0;
222*41c8c312SAmine Khaldi IDirectInput8_EnumDevicesBySemantics(data->lpDI, NULL, data->original_lpdiaf, collect_devices, (LPVOID) data, 0);
223c2c66affSColin Finck
224*41c8c312SAmine Khaldi for (i = 0; i < data->devices_data.ndevices; i++)
225*41c8c312SAmine Khaldi SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->devices_data.devices[i].ddi.tszProductName );
226*41c8c312SAmine Khaldi for (i = 0; i < data->nusernames; i++)
227*41c8c312SAmine Khaldi SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->usernames[i]);
228c2c66affSColin Finck }
229c2c66affSColin Finck
destroy_data(HWND dialog)230c2c66affSColin Finck static void destroy_data(HWND dialog)
231c2c66affSColin Finck {
232*41c8c312SAmine Khaldi int i, j;
233c2c66affSColin Finck ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
234c2c66affSColin Finck DIDevicesData *devices_data = &data->devices_data;
235c2c66affSColin Finck
236c2c66affSColin Finck /* Free the devices */
237c2c66affSColin Finck for (i=0; i < devices_data->ndevices; i++)
238*41c8c312SAmine Khaldi {
239c2c66affSColin Finck IDirectInputDevice8_Release(devices_data->devices[i].lpdid);
240*41c8c312SAmine Khaldi for (j=0; j < data->nusernames; j++)
241*41c8c312SAmine Khaldi heap_free(devices_data->devices[i].user_afs[j].rgoAction);
242*41c8c312SAmine Khaldi heap_free(devices_data->devices[i].user_afs);
243*41c8c312SAmine Khaldi }
244c2c66affSColin Finck
245c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, devices_data->devices);
246c2c66affSColin Finck }
247c2c66affSColin Finck
fill_device_object_list(HWND dialog)248c2c66affSColin Finck static void fill_device_object_list(HWND dialog)
249c2c66affSColin Finck {
250c2c66affSColin Finck DeviceData *device = get_cur_device(dialog);
251c2c66affSColin Finck LPDIACTIONFORMATW lpdiaf = get_cur_lpdiaf(dialog);
252c2c66affSColin Finck LVITEMW item;
253c2c66affSColin Finck int i, j;
254c2c66affSColin Finck
255c2c66affSColin Finck /* Clean the listview */
256c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_DELETEALLITEMS, 0, 0);
257c2c66affSColin Finck
258c2c66affSColin Finck /* Add each object */
259c2c66affSColin Finck for (i=0; i < device->nobjects; i++)
260c2c66affSColin Finck {
261*41c8c312SAmine Khaldi DWORD ddo_inst, ddo_type;
262c2c66affSColin Finck int action = -1;
263c2c66affSColin Finck
264c2c66affSColin Finck item.mask = LVIF_TEXT | LVIF_PARAM;
265c2c66affSColin Finck item.iItem = i;
266c2c66affSColin Finck item.iSubItem = 0;
267c2c66affSColin Finck item.pszText = device->ddo[i].tszName;
268c2c66affSColin Finck item.cchTextMax = lstrlenW(item.pszText);
269c2c66affSColin Finck
270c2c66affSColin Finck /* Add the item */
271c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTITEMW, 0, (LPARAM) &item);
272*41c8c312SAmine Khaldi ddo_inst = DIDFT_GETINSTANCE(device->ddo[i].dwType);
273*41c8c312SAmine Khaldi ddo_type = DIDFT_GETTYPE(device->ddo[i].dwType);
274c2c66affSColin Finck
275c2c66affSColin Finck /* Search for an assigned action for this device */
276c2c66affSColin Finck for (j=0; j < lpdiaf->dwNumActions; j++)
277c2c66affSColin Finck {
278*41c8c312SAmine Khaldi DWORD af_inst = DIDFT_GETINSTANCE(lpdiaf->rgoAction[j].dwObjID);
279*41c8c312SAmine Khaldi DWORD af_type = DIDFT_GETTYPE(lpdiaf->rgoAction[j].dwObjID);
280*41c8c312SAmine Khaldi if (af_type == DIDFT_PSHBUTTON) af_type = DIDFT_BUTTON;
281*41c8c312SAmine Khaldi if (af_type == DIDFT_RELAXIS) af_type = DIDFT_AXIS;
282*41c8c312SAmine Khaldi /* NOTE previously compared dwType == dwObjId but default buildActionMap actions
283*41c8c312SAmine Khaldi * were PSHBUTTON and RELAXS and didnt show up on config */
284c2c66affSColin Finck if (IsEqualGUID(&lpdiaf->rgoAction[j].guidInstance, &device->ddi.guidInstance) &&
285*41c8c312SAmine Khaldi ddo_inst == af_inst && ddo_type & af_type)
286c2c66affSColin Finck {
287c2c66affSColin Finck action = j;
288c2c66affSColin Finck break;
289c2c66affSColin Finck }
290c2c66affSColin Finck }
291c2c66affSColin Finck
292c2c66affSColin Finck lv_set_action(dialog, i, action, lpdiaf);
293c2c66affSColin Finck }
294c2c66affSColin Finck }
295c2c66affSColin Finck
show_suitable_actions(HWND dialog)296c2c66affSColin Finck static void show_suitable_actions(HWND dialog)
297c2c66affSColin Finck {
298c2c66affSColin Finck DeviceData *device = get_cur_device(dialog);
299*41c8c312SAmine Khaldi LPDIACTIONFORMATW lpdiaf = get_original_lpdiaf(dialog);
300c2c66affSColin Finck int i, added = 0;
301c2c66affSColin Finck int obj = lv_get_cur_item(dialog);
302c2c66affSColin Finck
303c2c66affSColin Finck if (obj < 0) return;
304c2c66affSColin Finck
305c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_RESETCONTENT, 0, 0);
306c2c66affSColin Finck
307c2c66affSColin Finck for (i=0; i < lpdiaf->dwNumActions; i++)
308c2c66affSColin Finck {
309c2c66affSColin Finck /* Skip keyboard actions for non keyboards */
310c2c66affSColin Finck if (GET_DIDEVICE_TYPE(device->ddi.dwDevType) != DI8DEVTYPE_KEYBOARD &&
311c2c66affSColin Finck (lpdiaf->rgoAction[i].dwSemantic & DIKEYBOARD_MASK) == DIKEYBOARD_MASK) continue;
312c2c66affSColin Finck
313c2c66affSColin Finck /* Skip mouse actions for non mouses */
314c2c66affSColin Finck if (GET_DIDEVICE_TYPE(device->ddi.dwDevType) != DI8DEVTYPE_MOUSE &&
315c2c66affSColin Finck (lpdiaf->rgoAction[i].dwSemantic & DIMOUSE_MASK) == DIMOUSE_MASK) continue;
316c2c66affSColin Finck
317c2c66affSColin Finck /* Add action string and index in the action format to the list entry */
318c2c66affSColin Finck if (DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwSemantic) & DIDFT_GETTYPE(device->ddo[obj].dwType))
319c2c66affSColin Finck {
320c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_ADDSTRING, 0, (LPARAM)lpdiaf->rgoAction[i].u.lptszActionName);
321c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_SETITEMDATA, added, (LPARAM) i);
322c2c66affSColin Finck added++;
323c2c66affSColin Finck }
324c2c66affSColin Finck }
325c2c66affSColin Finck }
326c2c66affSColin Finck
assign_action(HWND dialog)327c2c66affSColin Finck static void assign_action(HWND dialog)
328c2c66affSColin Finck {
329c2c66affSColin Finck DeviceData *device = get_cur_device(dialog);
330c2c66affSColin Finck LPDIACTIONFORMATW lpdiaf = get_cur_lpdiaf(dialog);
331c2c66affSColin Finck LVFINDINFOW lvFind;
332c2c66affSColin Finck int sel = SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_GETCURSEL, 0, 0);
333c2c66affSColin Finck int action = SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_GETITEMDATA, sel, 0);
334c2c66affSColin Finck int obj = lv_get_cur_item(dialog);
335c2c66affSColin Finck int old_action = lv_get_item_data(dialog, obj);
336c2c66affSColin Finck int used_obj;
337*41c8c312SAmine Khaldi DWORD type;
338c2c66affSColin Finck
339c2c66affSColin Finck if (old_action == action) return;
340*41c8c312SAmine Khaldi if (obj < 0) return;
341*41c8c312SAmine Khaldi if (lpdiaf->rgoAction[old_action].dwFlags & DIA_APPFIXED) return;
342*41c8c312SAmine Khaldi
343*41c8c312SAmine Khaldi type = device->ddo[obj].dwType;
344c2c66affSColin Finck
345c2c66affSColin Finck /* Clear old action */
346c2c66affSColin Finck if (old_action != -1)
347c2c66affSColin Finck {
348c2c66affSColin Finck lpdiaf->rgoAction[old_action].dwObjID = 0;
349c2c66affSColin Finck lpdiaf->rgoAction[old_action].guidInstance = GUID_NULL;
350c2c66affSColin Finck lpdiaf->rgoAction[old_action].dwHow = DIAH_UNMAPPED;
351c2c66affSColin Finck }
352c2c66affSColin Finck
353c2c66affSColin Finck /* Find if action text is already set for other object and unset it */
354c2c66affSColin Finck lvFind.flags = LVFI_PARAM;
355c2c66affSColin Finck lvFind.lParam = action;
356c2c66affSColin Finck
357c2c66affSColin Finck used_obj = SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_FINDITEMW, -1, (LPARAM) &lvFind);
358c2c66affSColin Finck
359c2c66affSColin Finck lv_set_action(dialog, used_obj, -1, lpdiaf);
360c2c66affSColin Finck
361c2c66affSColin Finck /* Set new action */
362*41c8c312SAmine Khaldi lpdiaf->rgoAction[action].dwObjID = type;
363c2c66affSColin Finck lpdiaf->rgoAction[action].guidInstance = device->ddi.guidInstance;
364c2c66affSColin Finck lpdiaf->rgoAction[action].dwHow = DIAH_USERCONFIG;
365c2c66affSColin Finck
366c2c66affSColin Finck /* Set new action in the list */
367c2c66affSColin Finck lv_set_action(dialog, obj, action, lpdiaf);
368c2c66affSColin Finck }
369c2c66affSColin Finck
reset_actions(HWND dialog)370c2c66affSColin Finck static void reset_actions(HWND dialog)
371c2c66affSColin Finck {
372c2c66affSColin Finck ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
373*41c8c312SAmine Khaldi DIDevicesData *ddata = (DIDevicesData*) &data->devices_data;
374*41c8c312SAmine Khaldi unsigned i, j;
375c2c66affSColin Finck
376*41c8c312SAmine Khaldi for (i = 0; i < data->devices_data.ndevices; i++)
377*41c8c312SAmine Khaldi {
378*41c8c312SAmine Khaldi DeviceData *device = &ddata->devices[i];
379*41c8c312SAmine Khaldi for (j = 0; j < data->nusernames; j++)
380*41c8c312SAmine Khaldi IDirectInputDevice8_BuildActionMap(device->lpdid, &device->user_afs[j], data->usernames[j], DIDBAM_HWDEFAULTS);
381*41c8c312SAmine Khaldi }
382*41c8c312SAmine Khaldi }
383*41c8c312SAmine Khaldi
save_actions(HWND dialog)384*41c8c312SAmine Khaldi static void save_actions(HWND dialog) {
385*41c8c312SAmine Khaldi ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
386*41c8c312SAmine Khaldi DIDevicesData *ddata = (DIDevicesData*) &data->devices_data;
387*41c8c312SAmine Khaldi unsigned i, j;
388*41c8c312SAmine Khaldi if (!data->display_only) {
389*41c8c312SAmine Khaldi for (i = 0; i < ddata->ndevices; i++)
390*41c8c312SAmine Khaldi {
391*41c8c312SAmine Khaldi DeviceData *device = &ddata->devices[i];
392*41c8c312SAmine Khaldi for (j = 0; j < data->nusernames; j++)
393*41c8c312SAmine Khaldi {
394*41c8c312SAmine Khaldi if (save_mapping_settings(device->lpdid, &device->user_afs[j], data->usernames[j]) != DI_OK)
395*41c8c312SAmine Khaldi MessageBoxA(dialog, "Could not save settings", 0, MB_ICONERROR);
396*41c8c312SAmine Khaldi }
397*41c8c312SAmine Khaldi }
398*41c8c312SAmine Khaldi }
399c2c66affSColin Finck }
400c2c66affSColin Finck
ConfigureDevicesDlgProc(HWND dialog,UINT uMsg,WPARAM wParam,LPARAM lParam)401c2c66affSColin Finck static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
402c2c66affSColin Finck {
403c2c66affSColin Finck switch(uMsg)
404c2c66affSColin Finck {
405c2c66affSColin Finck case WM_INITDIALOG:
406c2c66affSColin Finck {
407c2c66affSColin Finck ConfigureDevicesData *data = (ConfigureDevicesData*) lParam;
408c2c66affSColin Finck
409c2c66affSColin Finck /* Initialize action format and enumerate devices */
410*41c8c312SAmine Khaldi init_devices(dialog, data);
411c2c66affSColin Finck
412c2c66affSColin Finck /* Store information in the window */
413c2c66affSColin Finck SetWindowLongPtrW(dialog, DWLP_USER, (LONG_PTR) data);
414c2c66affSColin Finck
415c2c66affSColin Finck init_listview_columns(dialog);
416c2c66affSColin Finck
417c2c66affSColin Finck /* Select the first device and show its actions */
418c2c66affSColin Finck SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_SETCURSEL, 0, 0);
419*41c8c312SAmine Khaldi SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_SETCURSEL, 0, 0);
420c2c66affSColin Finck fill_device_object_list(dialog);
421c2c66affSColin Finck
422*41c8c312SAmine Khaldi ShowCursor(TRUE);
423*41c8c312SAmine Khaldi
424c2c66affSColin Finck break;
425c2c66affSColin Finck }
426c2c66affSColin Finck
427*41c8c312SAmine Khaldi case WM_DESTROY:
428*41c8c312SAmine Khaldi ShowCursor(FALSE);
429*41c8c312SAmine Khaldi break;
430*41c8c312SAmine Khaldi
431c2c66affSColin Finck case WM_NOTIFY:
432c2c66affSColin Finck
433c2c66affSColin Finck switch (((LPNMHDR)lParam)->code)
434c2c66affSColin Finck {
435c2c66affSColin Finck case LVN_ITEMCHANGED:
436c2c66affSColin Finck show_suitable_actions(dialog);
437c2c66affSColin Finck break;
438c2c66affSColin Finck }
439c2c66affSColin Finck break;
440c2c66affSColin Finck
441c2c66affSColin Finck
442c2c66affSColin Finck case WM_COMMAND:
443c2c66affSColin Finck
444c2c66affSColin Finck switch(LOWORD(wParam))
445c2c66affSColin Finck {
446c2c66affSColin Finck
447c2c66affSColin Finck case IDC_ACTIONLIST:
448c2c66affSColin Finck
449c2c66affSColin Finck switch (HIWORD(wParam))
450c2c66affSColin Finck {
451c2c66affSColin Finck case LBN_DBLCLK:
452c2c66affSColin Finck /* Ignore this if app did not ask for editing */
453c2c66affSColin Finck if (dialog_display_only(dialog)) break;
454c2c66affSColin Finck
455c2c66affSColin Finck assign_action(dialog);
456c2c66affSColin Finck break;
457c2c66affSColin Finck }
458c2c66affSColin Finck break;
459c2c66affSColin Finck
460c2c66affSColin Finck case IDC_CONTROLLERCOMBO:
461*41c8c312SAmine Khaldi case IDC_PLAYERCOMBO:
462c2c66affSColin Finck
463c2c66affSColin Finck switch (HIWORD(wParam))
464c2c66affSColin Finck {
465c2c66affSColin Finck case CBN_SELCHANGE:
466c2c66affSColin Finck fill_device_object_list(dialog);
467c2c66affSColin Finck break;
468c2c66affSColin Finck }
469c2c66affSColin Finck break;
470c2c66affSColin Finck
471c2c66affSColin Finck case IDOK:
472*41c8c312SAmine Khaldi save_actions(dialog);
473c2c66affSColin Finck EndDialog(dialog, 0);
474c2c66affSColin Finck destroy_data(dialog);
475c2c66affSColin Finck break;
476c2c66affSColin Finck
477c2c66affSColin Finck case IDCANCEL:
478c2c66affSColin Finck EndDialog(dialog, 0);
479c2c66affSColin Finck destroy_data(dialog);
480c2c66affSColin Finck break;
481c2c66affSColin Finck
482c2c66affSColin Finck case IDC_RESET:
483c2c66affSColin Finck reset_actions(dialog);
484c2c66affSColin Finck fill_device_object_list(dialog);
485c2c66affSColin Finck break;
486c2c66affSColin Finck }
487c2c66affSColin Finck break;
488c2c66affSColin Finck }
489c2c66affSColin Finck
490c2c66affSColin Finck return FALSE;
491c2c66affSColin Finck }
492c2c66affSColin Finck
_configure_devices(IDirectInput8W * iface,LPDICONFIGUREDEVICESCALLBACK lpdiCallback,LPDICONFIGUREDEVICESPARAMSW lpdiCDParams,DWORD dwFlags,LPVOID pvRefData)493c2c66affSColin Finck HRESULT _configure_devices(IDirectInput8W *iface,
494c2c66affSColin Finck LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
495c2c66affSColin Finck LPDICONFIGUREDEVICESPARAMSW lpdiCDParams,
496c2c66affSColin Finck DWORD dwFlags,
497c2c66affSColin Finck LPVOID pvRefData
498c2c66affSColin Finck )
499c2c66affSColin Finck {
500*41c8c312SAmine Khaldi int i;
501*41c8c312SAmine Khaldi DWORD size;
502*41c8c312SAmine Khaldi WCHAR *username = NULL;
503c2c66affSColin Finck ConfigureDevicesData data;
504c2c66affSColin Finck data.lpDI = iface;
505*41c8c312SAmine Khaldi data.original_lpdiaf = lpdiCDParams->lprgFormats;
506c2c66affSColin Finck data.display_only = !(dwFlags & DICD_EDIT);
507*41c8c312SAmine Khaldi data.nusernames = lpdiCDParams->dwcUsers;
508*41c8c312SAmine Khaldi if (lpdiCDParams->lptszUserNames == NULL)
509*41c8c312SAmine Khaldi {
510*41c8c312SAmine Khaldi /* Get default user name */
511*41c8c312SAmine Khaldi GetUserNameW(NULL, &size);
512*41c8c312SAmine Khaldi username = heap_alloc(size * sizeof(WCHAR) );
513*41c8c312SAmine Khaldi GetUserNameW(username, &size);
514*41c8c312SAmine Khaldi data.nusernames = 1;
515*41c8c312SAmine Khaldi data.usernames = heap_alloc(sizeof(WCHAR *));
516*41c8c312SAmine Khaldi data.usernames[0] = username;
517*41c8c312SAmine Khaldi }
518*41c8c312SAmine Khaldi else
519*41c8c312SAmine Khaldi {
520*41c8c312SAmine Khaldi WCHAR *p = lpdiCDParams->lptszUserNames;
521*41c8c312SAmine Khaldi data.usernames = heap_alloc(sizeof(WCHAR *) * data.nusernames);
522*41c8c312SAmine Khaldi for (i = 0; i < data.nusernames; i++)
523*41c8c312SAmine Khaldi {
524*41c8c312SAmine Khaldi if (*p)
525*41c8c312SAmine Khaldi {
526*41c8c312SAmine Khaldi data.usernames[i] = p;
527*41c8c312SAmine Khaldi while (*(p++));
528*41c8c312SAmine Khaldi }
529*41c8c312SAmine Khaldi else
530*41c8c312SAmine Khaldi /* Return if there is an empty string */
531*41c8c312SAmine Khaldi return DIERR_INVALIDPARAM;
532*41c8c312SAmine Khaldi }
533*41c8c312SAmine Khaldi }
534c2c66affSColin Finck
535c2c66affSColin Finck InitCommonControls();
536c2c66affSColin Finck
53798e62237SAmine Khaldi DialogBoxParamW(DINPUT_instance, (const WCHAR *)MAKEINTRESOURCE(IDD_CONFIGUREDEVICES),
53898e62237SAmine Khaldi lpdiCDParams->hwnd, ConfigureDevicesDlgProc, (LPARAM)&data);
539c2c66affSColin Finck
540*41c8c312SAmine Khaldi heap_free(username);
541*41c8c312SAmine Khaldi heap_free(data.usernames);
542*41c8c312SAmine Khaldi
543c2c66affSColin Finck return DI_OK;
544c2c66affSColin Finck }
545