4 * Copyright 2005 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
33 #include "wine/test.h"
35 static ATOM atomMenuCheckClass;
37 static LRESULT WINAPI menu_check_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
41 case WM_ENTERMENULOOP:
42 /* mark window as having entered menu loop */
43 SetWindowLongPtr(hwnd, GWLP_USERDATA, TRUE);
44 /* exit menu modal loop
45 * ( A SendMessage does not work on NT3.51 here ) */
46 return PostMessage(hwnd, WM_CANCELMODE, 0, 0);
48 return DefWindowProc(hwnd, msg, wparam, lparam);
51 /* globals to communicate between test and wndproc */
52 unsigned int MOD_maxid;
54 int MOD_avec, MOD_hic;
57 /* wndproc used by test_menu_ownerdraw() */
58 static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg,
59 WPARAM wparam, LPARAM lparam)
65 MEASUREITEMSTRUCT* pmis = (MEASUREITEMSTRUCT*)lparam;
67 trace("WM_MEASUREITEM received %d,%d\n",
68 pmis->itemWidth, pmis->itemHeight);
69 MOD_odheight = pmis->itemHeight;
70 pmis->itemWidth = MOD_SIZE;
71 pmis->itemHeight = MOD_SIZE;
76 DRAWITEMSTRUCT * pdis;
79 char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
81 pdis = (DRAWITEMSTRUCT *) lparam;
83 trace("WM_DRAWITEM received itemdata %ld item %d rc %ld,%ld-%ld,%ld\n",
85 pdis->itemID, pdis->rcItem.left, pdis->rcItem.top,
86 pdis->rcItem.right,pdis->rcItem.bottom );
87 oldpen=SelectObject( pdis->hDC, GetStockObject(
88 pdis->itemState & ODS_SELECTED ? WHITE_PEN :BLACK_PEN));
89 Rectangle( pdis->hDC, pdis->rcItem.left,pdis->rcItem.top,
90 pdis->rcItem.right,pdis->rcItem.bottom );
91 SelectObject( pdis->hDC, oldpen);
93 if( pdis->itemData > MOD_maxid) return TRUE;
94 /* store the rectangl */
95 MOD_rc[pdis->itemData] = pdis->rcItem;
96 /* calculate average character width */
97 GetTextExtentPoint( pdis->hDC, chrs, 52, &sz );
98 MOD_avec = (sz.cx + 26)/52;
99 GetTextMetrics( pdis->hDC, &tm);
100 MOD_hic = tm.tmHeight;
101 if( pdis->itemData == MOD_maxid) PostMessage(hwnd, WM_CANCELMODE, 0, 0);
106 return DefWindowProc(hwnd, msg, wparam, lparam);
109 static void register_menu_check_class(void)
117 GetModuleHandle(NULL),
119 LoadCursor(NULL, IDC_ARROW),
120 (HBRUSH)(COLOR_BTNFACE+1),
122 TEXT("WineMenuCheck"),
125 atomMenuCheckClass = RegisterClass(&wc);
128 /* demonstrates that windows lock the menu object so that it is still valid
129 * even after a client calls DestroyMenu on it */
130 static void test_menu_locked_by_window(void)
134 HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
135 WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
136 NULL, NULL, NULL, NULL);
137 ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
138 hmenu = CreateMenu();
139 ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
140 ret = InsertMenu(hmenu, 0, MF_STRING, 0, TEXT("&Test"));
141 ok(ret, "InsertMenu failed with error %ld\n", GetLastError());
142 ret = SetMenu(hwnd, hmenu);
143 ok(ret, "SetMenu failed with error %ld\n", GetLastError());
144 ret = DestroyMenu(hmenu);
145 ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
147 ret = DrawMenuBar(hwnd);
149 ok(ret, "DrawMenuBar failed with error %ld\n", GetLastError());
151 ret = IsMenu(GetMenu(hwnd));
152 ok(!ret, "Menu handle should have been destroyed\n");
154 SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
155 /* did we process the WM_INITMENU message? */
156 ret = GetWindowLongPtr(hwnd, GWLP_USERDATA);
158 ok(ret, "WM_INITMENU should have been sent\n");
164 static void test_menu_ownerdraw(void)
170 HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
171 WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
172 NULL, NULL, NULL, NULL);
173 ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
175 SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG)menu_ownerdraw_wnd_proc);
176 hmenu = CreatePopupMenu();
177 ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
178 if( !hmenu) { DestroyWindow(hwnd);return;}
180 for( j=0;j<2;j++) /* create columns */
181 for(i=0;i<2;i++) { /* create rows */
182 ret = AppendMenu( hmenu, MF_OWNERDRAW |
183 (i==0 ? MF_MENUBREAK : 0), k, (LPCTSTR) k);
185 ok( ret, "AppendMenu failed for %d\n", k-1);
188 assert( k <= sizeof(MOD_rc)/sizeof(RECT));
189 /* display the menu */
190 ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
192 /* columns have a 4 pixel gap between them */
193 ok( MOD_rc[0].right + 4 == MOD_rc[2].left,
194 "item rectangles are not separated by 4 pixels space\n");
195 /* height should be what the MEASUREITEM message has returned */
196 ok( MOD_rc[0].bottom - MOD_rc[0].top == MOD_SIZE,
197 "menu item has wrong height: %ld should be %d\n",
198 MOD_rc[0].bottom - MOD_rc[0].top, MOD_SIZE);
199 /* no gaps between the rows */
200 ok( MOD_rc[0].bottom - MOD_rc[1].top == 0,
201 "There should not be a space between the rows, gap is %ld\n",
202 MOD_rc[0].bottom - MOD_rc[1].top);
203 /* test the correct value of the item height that was sent
204 * by the WM_MEASUREITEM message */
205 ok( MOD_odheight == HIWORD( GetDialogBaseUnits()) || /* WinNT,2k,XP */
206 MOD_odheight == MOD_hic, /* Win95,98,ME */
207 "Wrong height field in MEASUREITEMSTRUCT, expected %d or %d actual %d\n",
208 HIWORD( GetDialogBaseUnits()), MOD_hic, MOD_odheight);
209 /* test what MF_MENUBREAK did at the first position. Also show
210 * that an MF_SEPARATOR is ignored in the height calculation. */
211 leftcol= MOD_rc[0].left;
212 ModifyMenu( hmenu, 0, MF_BYCOMMAND| MF_OWNERDRAW| MF_SEPARATOR, 0, 0);
213 /* display the menu */
214 ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
215 /* left should be 4 pixels less now */
216 ok( leftcol == MOD_rc[0].left + 4,
217 "columns should be 4 pixels to the left (actual %ld).\n",
218 leftcol - MOD_rc[0].left);
220 ok( MOD_rc[0].right - MOD_rc[0].left == 2 * MOD_avec + MOD_SIZE,
221 "width of owner drawn menu item is wrong. Got %ld expected %d\n",
222 MOD_rc[0].right - MOD_rc[0].left , 2*MOD_avec + MOD_SIZE);
224 ok( MOD_rc[0].bottom - MOD_rc[0].top == MOD_SIZE,
225 "Height is incorrect. Got %ld expected %d\n",
226 MOD_rc[0].bottom - MOD_rc[0].top, MOD_SIZE);
228 /* test width/height of a OD menu bar as well */
229 ret = DestroyMenu(hmenu);
230 ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
231 hmenu = CreateMenu();
232 ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
233 if( !hmenu) { DestroyWindow(hwnd);return;}
236 ret = AppendMenu( hmenu, MF_OWNERDRAW , i, 0);
237 ok( ret, "AppendMenu failed for %d\n", i);
239 SetMenu( hwnd, hmenu);
240 UpdateWindow( hwnd); /* hack for wine to draw the window + menu */
241 ok(ret, "SetMenu failed with error %ld\n", GetLastError());
243 ok( MOD_rc[0].right - MOD_rc[0].left == 2 * MOD_avec + MOD_SIZE,
244 "width of owner drawn menu item is wrong. Got %ld expected %d\n",
245 MOD_rc[0].right - MOD_rc[0].left , 2*MOD_avec + MOD_SIZE);
247 ok( MOD_rc[0].bottom - MOD_rc[0].top == GetSystemMetrics( SM_CYMENU) - 1,
248 "Height of owner drawn menu item is wrong. Got %ld expected %d\n",
249 MOD_rc[0].bottom - MOD_rc[0].top, GetSystemMetrics( SM_CYMENU) - 1);
254 static void test_menu_add_string( void )
264 WCHAR strbackW[0x80];
265 static const WCHAR expectedString[] = {'D', 'u', 'm', 'm', 'y', ' ',
266 's', 't', 'r', 'i', 'n', 'g', 0};
268 hmenu = CreateMenu();
270 memset( &info, 0, sizeof info );
271 info.cbSize = sizeof info;
272 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_ID;
273 info.dwTypeData = "blah";
278 InsertMenuItem(hmenu, 0, TRUE, &info );
280 memset( &info, 0, sizeof info );
281 info.cbSize = sizeof info;
282 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_DATA | MIIM_ID;
283 info.dwTypeData = string;
284 info.cch = sizeof string;
286 GetMenuItemInfo( hmenu, 0, TRUE, &info );
288 ok( !strcmp( string, "blah" ), "menu item name differed\n");
290 /* Test combination of ownerdraw and strings with GetMenuItemString(A/W) */
291 strcpy(string, "Dummy string");
292 memset(&info, 0x00, sizeof(info));
293 info.cbSize= sizeof(MENUITEMINFO);
294 info.fMask= MIIM_FTYPE | MIIM_STRING; /* Set OwnerDraw + typeData */
295 info.fType= MFT_OWNERDRAW;
296 info.dwTypeData= string;
297 rc = InsertMenuItem( hmenu, 0, TRUE, &info );
298 ok (rc, "InsertMenuItem failed\n");
300 strcpy(string,"Garbage");
301 ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
302 ok (!strcmp( strback, "Dummy string" ), "Menu text from Ansi version incorrect\n");
304 ok (GetMenuStringW( hmenu, 0, (WCHAR *)strbackW, 99, MF_BYPOSITION), "GetMenuStringW on ownerdraw entry failed\n");
305 ok (!lstrcmpW( strbackW, expectedString ), "Menu text from Unicode version incorrect\n");
307 /* Just change ftype to string and see what text is stored */
308 memset(&info, 0x00, sizeof(info));
309 info.cbSize= sizeof(MENUITEMINFO);
310 info.fMask= MIIM_FTYPE; /* Set string type */
311 info.fType= MFT_STRING;
312 info.dwTypeData= (char *)0xdeadbeef;
313 rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
314 ok (rc, "SetMenuItemInfo failed\n");
316 /* Did we keep the old dwTypeData? */
317 ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
318 ok (!strcmp( strback, "Dummy string" ), "Menu text from Ansi version incorrect\n");
320 /* Ensure change to bitmap type fails */
321 memset(&info, 0x00, sizeof(info));
322 info.cbSize= sizeof(MENUITEMINFO);
323 info.fMask= MIIM_FTYPE; /* Set as bitmap type */
324 info.fType= MFT_BITMAP;
325 info.dwTypeData= (char *)0xdeadbee2;
326 rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
327 ok (!rc, "SetMenuItemInfo unexpectedly worked\n");
329 /* Just change ftype back and ensure data hasnt been freed */
330 info.fType= MFT_OWNERDRAW; /* Set as ownerdraw type */
331 info.dwTypeData= (char *)0xdeadbee3;
332 rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
333 ok (rc, "SetMenuItemInfo failed\n");
335 /* Did we keep the old dwTypeData? */
336 ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
337 ok (!strcmp( strback, "Dummy string" ), "Menu text from Ansi version incorrect\n");
339 /* Just change string value (not type) */
340 memset(&info, 0x00, sizeof(info));
341 info.cbSize= sizeof(MENUITEMINFO);
342 info.fMask= MIIM_STRING; /* Set typeData */
343 strcpy(string2, "string2");
344 info.dwTypeData= string2;
345 rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
346 ok (rc, "SetMenuItemInfo failed\n");
348 ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
349 ok (!strcmp( strback, "string2" ), "Menu text from Ansi version incorrect\n");
351 /* crashes with wine 0.9.5 */
352 memset(&info, 0x00, sizeof(info));
353 info.cbSize= sizeof(MENUITEMINFO);
354 info.fMask= MIIM_FTYPE | MIIM_STRING; /* Set OwnerDraw + typeData */
355 info.fType= MFT_OWNERDRAW;
356 rc = InsertMenuItem( hmenu, 0, TRUE, &info );
357 ok (rc, "InsertMenuItem failed\n");
358 ok (!GetMenuString( hmenu, 0, NULL, 0, MF_BYPOSITION),
359 "GetMenuString on ownerdraw entry succeeded.\n");
360 ok (!GetMenuStringW( hmenu, 0, NULL, 0, MF_BYPOSITION),
361 "GetMenuStringW on ownerdraw entry succeeded.\n");
364 DestroyMenu( hmenu );
367 /* define building blocks for the menu item info tests */
368 static int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
370 if (n <= 0) return 0;
371 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
372 return *str1 - *str2;
375 static WCHAR *strcpyW( WCHAR *dst, const WCHAR *src )
378 while ((*p++ = *src++));
383 #define DMIINFF( i, e, field)\
384 ok((int)((i)->field)==(int)((e)->field) || (int)((i)->field)==(0xffff & (int)((e)->field)), \
385 "%s got 0x%x expected 0x%x\n", #field, (int)((i)->field), (int)((e)->field));
387 #define DUMPMIINF(s,i,e)\
389 DMIINFF( i, e, fMask)\
390 DMIINFF( i, e, fType)\
391 DMIINFF( i, e, fState)\
393 DMIINFF( i, e, hSubMenu)\
394 DMIINFF( i, e, hbmpChecked)\
395 DMIINFF( i, e, hbmpUnchecked)\
396 DMIINFF( i, e, dwItemData)\
397 DMIINFF( i, e, dwTypeData)\
399 if( s==sizeof(MENUITEMINFOA)) DMIINFF( i, e, hbmpItem)\
402 /* insert menu item */
403 #define TMII_INSMI( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
406 MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
407 HMENU hmenu = CreateMenu();\
408 BOOL ret, stop = FALSE;\
409 SetLastError( 0xdeadbeef);\
410 if(ansi)strcpy( string, init);\
411 else strcpyW( (WCHAR*)string, (WCHAR*)init);\
412 if( ansi) ret = InsertMenuItemA(hmenu, 0, TRUE, &info1 );\
413 else ret = InsertMenuItemW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
414 if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
416 } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
419 /* GetMenuItemInfo + GetMenuString */
420 #define TMII_GMII( a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,\
421 a3,b3,c3,d3,e3,f3,g3,h3,i3,j3,k3,l3,m3,n3,\
422 expname, eret2, eret3)\
424 MENUITEMINFOA info2A=a2 b2,c2,d2,e2,f2,(void*)g2,(void*)h2,(void*)i2,j2,(void*)k2,l2,(void*)m2 n2;\
425 MENUITEMINFOA einfoA=a3 b3,c3,d3,e3,f3,(void*)g3,(void*)h3,(void*)i3,j3,(void*)k3,l3,(void*)m3 n3;\
426 MENUITEMINFOA *info2 = &info2A;\
427 MENUITEMINFOA *einfo = &einfoA;\
428 MENUITEMINFOW *info2W = (MENUITEMINFOW *)&info2A;\
430 ret = ansi ? GetMenuItemInfoA( hmenu, 0, TRUE, info2 ) :\
431 GetMenuItemInfoW( hmenu, 0, TRUE, info2W );\
432 if( !(eret2)) ok( (eret2)==ret,"GetMenuItemInfo should have failed.\n");\
434 ok( (eret2)==ret,"GetMenuItemInfo failed, err %ld\n",GetLastError());\
435 ret = memcmp( info2, einfo, sizeof einfoA);\
436 /* ok( ret==0, "Got wrong menu item info data\n");*/\
437 if( ret) DUMPMIINF(info2A.cbSize, &info2A, &einfoA)\
438 if( einfo->dwTypeData == string) {\
439 if(ansi) ok( !strncmp( expname, info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
440 einfo->dwTypeData ? einfo->dwTypeData: "");\
441 else ok( !strncmpW( (WCHAR*)expname, (WCHAR*)info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
442 einfo->dwTypeData ? einfo->dwTypeData: "");\
443 ret = ansi ? GetMenuStringA( hmenu, 0, string, 80, MF_BYPOSITION) :\
444 GetMenuStringW( hmenu, 0, string, 80, MF_BYPOSITION);\
446 ok( ret, "GetMenuString failed, err %ld\n",GetLastError());\
448 ok( !ret, "GetMenuString should have failed\n");\
455 RemoveMenu(hmenu, 0, TRUE );\
456 DestroyMenu( hmenu );\
457 DestroyMenu( submenu );\
458 submenu = CreateMenu();\
461 #define TMII_MODM( flags, id, data, eret )\
463 if(ansi)ret = ModifyMenuA( hmenu, 0, flags, (UINT_PTR)id, (char*)data);\
464 else ret = ModifyMenuW( hmenu, 0, flags, (UINT_PTR)id, (WCHAR*)data);\
465 if( !(eret)) ok( (eret)==ret,"ModifyMenuA should have failed.\n");\
466 else ok( (eret)==ret,"ModifyMenuA failed, err %ld\n",GetLastError());\
469 /* SetMenuItemInfo */
470 #define TMII_SMII( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
473 MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
474 SetLastError( 0xdeadbeef);\
475 if(ansi)strcpy( string, init);\
476 else strcpyW( (WCHAR*)string, (WCHAR*)init);\
477 if( ansi) ret = SetMenuItemInfoA(hmenu, 0, TRUE, &info1 );\
478 else ret = SetMenuItemInfoW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
479 if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
481 } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
490 static void test_menu_iteminfo( )
492 int S=sizeof( MENUITEMINFOA);
497 WCHAR txtW[]={'W','i','n','e',0};
498 WCHAR initW[]={'X','Y','Z',0};
500 void *txt, *init, *empty, *string;
501 HBITMAP hbm = CreateBitmap(1,1,1,1,NULL);
503 HMENU submenu=CreateMenu();
506 if( ansi) {txt=txtA;init=initA;empty=emptyA;string=stringA;}
507 else {txt=txtW;init=initW;empty=emptyW;string=stringA;}
508 trace( "%s string %p hbm %p txt %p\n", ansi ? "ANSI tests: " : "Unicode tests:", string, hbm, txt);
509 /* test all combinations of MFT_STRING, MFT_OWNERDRAW and MFT_BITMAP */
510 /* (since MFT_STRING is zero, there are four of them) */
511 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, 0, 0, 0, 0, 0, 0, txt, 0, 0, }, OK)
512 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
513 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
516 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
517 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
518 {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
521 TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
522 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
523 {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
526 TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
527 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
528 {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
531 /* not enough space for name*/
532 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
533 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, NULL, 0, -9, },
534 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, NULL, 4, 0, },
537 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
538 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 5, -9, },
539 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
542 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
543 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 4, -9, },
544 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 3, 0, },
547 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
548 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, NULL, 0, -9, },
549 {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 0, 0, },
552 /* can not combine MIIM_TYPE with some other flags */
553 TMII_INSMI( {, S, MIIM_TYPE|MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, ER)
554 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
555 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
558 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
559 TMII_GMII ( {, S, MIIM_TYPE|MIIM_STRING, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
560 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
563 TMII_INSMI( {, S, MIIM_TYPE|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, ER)
564 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
565 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
568 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
569 TMII_GMII ( {, S, MIIM_TYPE|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
570 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
573 TMII_INSMI( {, S, MIIM_TYPE|MIIM_BITMAP, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, 6, hbm, }, ER)
574 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
575 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
578 /* but succeeds with some others */
579 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
580 TMII_GMII ( {, S, MIIM_TYPE|MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
581 {, S, MIIM_TYPE|MIIM_SUBMENU, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
584 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
585 TMII_GMII ( {, S, MIIM_TYPE|MIIM_STATE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
586 {, S, MIIM_TYPE|MIIM_STATE, MFT_STRING, 0, -9, 0, -9, -9, -9, string, 4, 0, },
589 TMII_INSMI( {, S, MIIM_TYPE|MIIM_ID, MFT_STRING, -1, 888, -1, -1, -1, -1, txt, 6, -1, }, OK)
590 TMII_GMII ( {, S, MIIM_TYPE|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
591 {, S, MIIM_TYPE|MIIM_ID, MFT_STRING, -9, 888, 0, -9, -9, -9, string, 4, 0, },
594 TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING, -1, -1, -1, -1, -1, 999, txt, 6, -1, }, OK)
595 TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
596 {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING, -9, -9, 0, -9, -9, 999, string, 4, 0, },
599 /* to be continued */
600 /* set text with MIIM_TYPE and retrieve with MIIM_STRING */
601 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
602 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
603 {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, -9, },
606 /* set text with MIIM_TYPE and retrieve with MIIM_STRING; MFT_OWNERDRAW causes an empty string */
607 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
608 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
609 {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
612 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
613 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
614 {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
617 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
618 TMII_GMII ( {, S, MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
619 {, S, MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 80, -9, },
622 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
623 TMII_GMII ( {, S, 0, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
624 {, S, 0, -9, -9, -9, 0, -9, -9, -9, string, 80, -9, },
627 /* contrary to MIIM_TYPE,you can set the text for an owner draw menu */
628 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
629 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
630 {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 4, -9, },
633 /* same but retrieve with MIIM_TYPE */
634 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
635 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
636 {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
639 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
640 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
641 {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
644 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
645 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
646 {, S, MIIM_STRING|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 0, -9, },
650 /* How is that with bitmaps? */
651 TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
652 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
653 {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
656 TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
657 TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
658 {, S, MIIM_BITMAP|MIIM_FTYPE, 0, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
661 /* MIIM_BITMAP does not like MFT_BITMAP */
662 TMII_INSMI( {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, ER)
663 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
664 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
667 /* no problem with OWNERDRAWN */
668 TMII_INSMI( {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
669 TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
670 {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
673 /* setting MFT_BITMAP with MFT_FTYPE fails anyway */
674 TMII_INSMI( {, S, MIIM_FTYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, ER)
675 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
676 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
680 /* menu with submenu */
681 TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, txt, 0, -1, }, OK)
682 TMII_GMII ( {, S, MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
683 {, S, MIIM_SUBMENU, -9, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
686 TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, empty, 0, -1, }, OK)
687 TMII_GMII ( {, S, MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
688 {, S, MIIM_SUBMENU, -9, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
691 /* menu with submenu, without MIIM_SUBMENU the submenufield is cleared */
692 TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, txt, 0, -1, }, OK)
693 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
694 {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 0, -9, },
696 TMII_GMII ( {, S, MIIM_SUBMENU|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
697 {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
700 /* menu with invalid submenu */
701 TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, 999, -1, -1, -1, txt, 0, -1, }, ER)
702 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
703 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
707 TMII_INSMI( {, S, MIIM_TYPE, MFT_SEPARATOR, 0, 0, 0, 0, 0, 0, txt, 0, 0, }, OK)
708 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
709 {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
712 TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP|MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
713 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
714 {, S, MIIM_TYPE, MFT_BITMAP|MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
717 /* SEPARATOR and STRING go well together */
718 /* BITMAP and STRING go well together */
719 TMII_INSMI( {, S, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
720 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
721 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, hbm, },
724 /* BITMAP, SEPARATOR and STRING go well together */
725 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
726 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
727 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 4, hbm, },
730 /* last two tests, but use MIIM_TYPE to retrieve info */
731 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
732 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
733 {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
736 TMII_INSMI( {, S, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
737 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
738 {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
741 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
742 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
743 {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
746 /* same three with MFT_OWNERDRAW */
747 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
748 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
749 {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
752 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
753 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
754 {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
757 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
758 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
759 {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
763 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE|MIIM_ID, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
764 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
765 {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
768 /* test with modifymenu: string is preserved after seting OWNERDRAW */
769 TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
770 TMII_MODM( MFT_OWNERDRAW, -1, 787, OK)
771 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
772 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_DATA, MFT_OWNERDRAW, -9, -9, 0, -9, -9, 787, string, 4, -9, },
775 /* same with bitmap: now the text is cleared */
776 TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
777 TMII_MODM( MFT_BITMAP, 545, hbm, OK)
778 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
779 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_BITMAP, -9, 545, 0, -9, -9, -9, string, 0, hbm, },
782 /* start with bitmap: now setting text clears it (though he flag is raised) */
783 TMII_INSMI( {, S, MIIM_BITMAP, MFT_STRING, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
784 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
785 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 0, 0, -9, -9, -9, string, 0, hbm, },
787 TMII_MODM( MFT_STRING, 545, txt, OK)
788 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
789 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 545, 0, -9, -9, -9, string, 4, 0, },
792 /*repeat with text NULL */
793 TMII_INSMI( {, S, MIIM_BITMAP, MFT_STRING, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
794 TMII_MODM( MFT_STRING, 545, NULL, OK)
795 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
796 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_SEPARATOR, -9, 545, 0, -9, -9, -9, string, 0, 0, },
799 /* repeat with text "" */
800 TMII_INSMI( {, S, MIIM_BITMAP, -1 , -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
801 TMII_MODM( MFT_STRING, 545, empty, OK)
802 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
803 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 545, 0, -9, -9, -9, string, 0, 0, },
806 /* start with bitmap: set ownerdraw */
807 TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
808 TMII_MODM( MFT_OWNERDRAW, -1, 232, OK)
809 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
810 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_DATA, MFT_OWNERDRAW, -9, -9, 0, -9, -9, 232, string, 0, hbm, },
814 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
815 TMII_GMII ( {, S, 0, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
816 {, S, 0, -9, -9, -9, 0, -9, -9, -9, string, 80, -9, },
819 /* some tests with small cbSize: the hbmpItem is to be ignored */
820 TMII_INSMI( {, S - 4, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
821 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
822 {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 0, NULL, },
825 TMII_INSMI( {, S - 4, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
826 TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
827 {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 80, NULL, },
830 TMII_INSMI( {, S - 4, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
831 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
832 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, NULL, },
835 TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
836 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
837 {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
840 TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
841 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
842 {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
845 TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
846 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
847 {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
850 /* MIIM_TYPE by itself does not get/set the dwItemData for OwnerDrawn menus */
851 TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
852 TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
853 {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, 343, 0, 0, 0, },
856 TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
857 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
858 {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
861 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
862 TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
863 {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, 0, 0, 0, 0, },
866 /* set a string menu to ownerdraw with MIIM_TYPE */
867 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -2, -2, -2, -2, -2, -2, txt, -2, -2, }, OK)
868 TMII_SMII( {, S, MIIM_TYPE, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, OK)
869 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
870 {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 4, -9, },
873 /* test with modifymenu add submenu */
874 TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
875 TMII_MODM( MF_POPUP, submenu, txt, OK)
876 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
877 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_SUBMENU, MFT_STRING, -9, -9, submenu, -9, -9, -9, string, 4, -9, },
879 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
880 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
890 The following tests try to confirm the algorithum used to return the menu items
891 when there is a collision between a menu item and a popup menu
893 void test_menu_search_bycommand( void )
895 HMENU hmenu, hmenuSub, hmenuSub2;
902 /* Case 1: Menu containing a menu item */
903 hmenu = CreateMenu();
905 memset( &info, 0, sizeof info );
906 info.cbSize = sizeof info;
907 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
908 info.fType = MFT_STRING;
909 strcpy(strIn, "Case 1 MenuItem");
910 info.dwTypeData = strIn;
911 info.wID = (UINT) 0x1234;
913 rc = InsertMenuItem(hmenu, 0, TRUE, &info );
914 ok (rc, "Inserting the menuitem failed\n");
916 id = GetMenuItemID(hmenu, 0);
917 ok (id == 0x1234, "Getting the menuitem id failed(gave %x)\n", id);
919 /* Confirm the menuitem was given the id supplied (getting by position) */
920 memset( &info, 0, sizeof info );
922 info.cbSize = sizeof(MENUITEMINFO);
923 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
924 info.dwTypeData = strback;
925 info.cch = sizeof(strback);
927 rc = GetMenuItemInfo(hmenu, 0, TRUE, &info); /* Get by position */
928 ok (rc, "Getting the menu items info failed\n");
929 ok (info.wID == 0x1234, "IDs differ for the menuitem\n");
930 ok (!strcmp(info.dwTypeData, "Case 1 MenuItem"), "Returned item has wrong label\n");
932 /* Search by id - Should return the item */
933 memset( &info, 0, sizeof info );
935 info.cbSize = sizeof(MENUITEMINFO);
936 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
937 info.dwTypeData = strback;
938 info.cch = sizeof(strback);
939 rc = GetMenuItemInfo(hmenu, 0x1234, FALSE, &info); /* Get by ID */
941 ok (rc, "Getting the menu items info failed\n");
942 ok (info.wID == 0x1234, "IDs differ for the menuitem\n");
943 ok (!strcmp(info.dwTypeData, "Case 1 MenuItem"), "Returned item has wrong label\n");
945 DestroyMenu( hmenu );
947 /* Case 2: Menu containing a popup menu */
948 hmenu = CreateMenu();
949 hmenuSub = CreateMenu();
951 strcpy(strIn, "Case 2 SubMenu");
952 rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, strIn);
953 ok (rc, "Inserting the popup menu into the main menu failed\n");
955 id = GetMenuItemID(hmenu, 0);
956 ok (id == -1, "Getting the menuitem id unexpectedly worked (gave %x)\n", id);
958 /* Confirm the menuitem itself was given an id the same as the HMENU, (getting by position) */
959 memset( &info, 0, sizeof info );
961 info.cbSize = sizeof(MENUITEMINFO);
962 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
963 info.dwTypeData = strback;
964 info.cch = sizeof(strback);
965 info.wID = 0xdeadbeef;
967 rc = GetMenuItemInfo(hmenu, 0, TRUE, &info); /* Get by position */
968 ok (rc, "Getting the menu items info failed\n");
969 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the menuitem\n");
970 ok (!strcmp(info.dwTypeData, "Case 2 SubMenu"), "Returned item has wrong label\n");
972 /* Search by id - returns the popup menu itself */
973 memset( &info, 0, sizeof info );
975 info.cbSize = sizeof(MENUITEMINFO);
976 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
977 info.dwTypeData = strback;
978 info.cch = sizeof(strback);
979 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
981 ok (rc, "Getting the menu items info failed\n");
982 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
983 ok (!strcmp(info.dwTypeData, "Case 2 SubMenu"), "Returned item has wrong label\n");
986 Now add an item after it with the same id
988 memset( &info, 0, sizeof info );
989 info.cbSize = sizeof info;
990 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
991 info.fType = MFT_STRING;
992 strcpy(strIn, "Case 2 MenuItem 1");
993 info.dwTypeData = strIn;
994 info.wID = (UINT_PTR) hmenuSub;
995 rc = InsertMenuItem(hmenu, -1, TRUE, &info );
996 ok (rc, "Inserting the menuitem failed\n");
998 /* Search by id - returns the item which follows the popup menu */
999 memset( &info, 0, sizeof info );
1001 info.cbSize = sizeof(MENUITEMINFO);
1002 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
1003 info.dwTypeData = strback;
1004 info.cch = sizeof(strback);
1005 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
1007 ok (rc, "Getting the menu items info failed\n");
1008 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
1009 ok (!strcmp(info.dwTypeData, "Case 2 MenuItem 1"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1012 Now add an item before the popup (with the same id)
1014 memset( &info, 0, sizeof info );
1015 info.cbSize = sizeof info;
1016 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1017 info.fType = MFT_STRING;
1018 strcpy(strIn, "Case 2 MenuItem 2");
1019 info.dwTypeData = strIn;
1020 info.wID = (UINT_PTR) hmenuSub;
1021 rc = InsertMenuItem(hmenu, 0, TRUE, &info );
1022 ok (rc, "Inserting the menuitem failed\n");
1024 /* Search by id - returns the item which preceeds the popup menu */
1025 memset( &info, 0, sizeof info );
1027 info.cbSize = sizeof(MENUITEMINFO);
1028 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
1029 info.dwTypeData = strback;
1030 info.cch = sizeof(strback);
1031 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
1033 ok (rc, "Getting the menu items info failed\n");
1034 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
1035 ok (!strcmp(info.dwTypeData, "Case 2 MenuItem 2"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1037 DestroyMenu( hmenu );
1038 DestroyMenu( hmenuSub );
1041 Case 3: Menu containing a popup menu which in turn
1042 contains 2 items with the same id as the popup itself
1045 hmenu = CreateMenu();
1046 hmenuSub = CreateMenu();
1048 memset( &info, 0, sizeof info );
1049 info.cbSize = sizeof info;
1050 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1051 info.fType = MFT_STRING;
1052 info.dwTypeData = "MenuItem";
1053 info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
1055 rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, "Submenu");
1056 ok (rc, "Inserting the popup menu into the main menu failed\n");
1058 rc = InsertMenuItem(hmenuSub, 0, TRUE, &info );
1059 ok (rc, "Inserting the sub menu menuitem failed\n");
1061 memset( &info, 0, sizeof info );
1062 info.cbSize = sizeof info;
1063 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1064 info.fType = MFT_STRING;
1065 info.dwTypeData = "MenuItem 2";
1066 info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
1068 rc = InsertMenuItem(hmenuSub, 1, TRUE, &info );
1069 ok (rc, "Inserting the sub menu menuitem 2 failed\n");
1071 /* Prove that you cant query the id of a popup directly (By position) */
1072 id = GetMenuItemID(hmenu, 0);
1073 ok (id == -1, "Getting the sub menu id should have failed because its a popup (gave %x)\n", id);
1075 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
1076 memset( &info, 0, sizeof info );
1078 info.cbSize = sizeof(MENUITEMINFO);
1079 info.fMask = MIIM_STRING | MIIM_ID;
1080 info.dwTypeData = strback;
1081 info.cch = sizeof(strback);
1083 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info);
1084 ok (rc, "Getting the menus info failed\n");
1085 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for popup menu\n");
1086 ok (!strcmp(info.dwTypeData, "MenuItem"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1087 DestroyMenu( hmenu );
1088 DestroyMenu( hmenuSub );
1091 Case 4: Menu containing 2 popup menus, the second
1092 contains 2 items with the same id as the first popup menu
1094 hmenu = CreateMenu();
1095 hmenuSub = CreateMenu();
1096 hmenuSub2 = CreateMenu();
1098 rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, "Submenu");
1099 ok (rc, "Inserting the popup menu into the main menu failed\n");
1101 rc = InsertMenu(hmenu, 1, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub2, "Submenu2");
1102 ok (rc, "Inserting the popup menu into the main menu failed\n");
1104 memset( &info, 0, sizeof info );
1105 info.cbSize = sizeof info;
1106 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1107 info.fType = MFT_STRING;
1108 info.dwTypeData = "MenuItem";
1109 info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
1111 rc = InsertMenuItem(hmenuSub2, 0, TRUE, &info );
1112 ok (rc, "Inserting the sub menu menuitem failed\n");
1114 memset( &info, 0, sizeof info );
1115 info.cbSize = sizeof info;
1116 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1117 info.fType = MFT_STRING;
1118 info.dwTypeData = "MenuItem 2";
1119 info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
1121 rc = InsertMenuItem(hmenuSub2, 1, TRUE, &info );
1122 ok (rc, "Inserting the sub menu menuitem 2 failed\n");
1124 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
1125 memset( &info, 0, sizeof info );
1127 info.cbSize = sizeof(MENUITEMINFO);
1128 info.fMask = MIIM_STRING | MIIM_ID;
1129 info.dwTypeData = strback;
1130 info.cch = sizeof(strback);
1132 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info);
1133 ok (rc, "Getting the menus info failed\n");
1134 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for popup menu\n");
1135 ok (!strcmp(info.dwTypeData, "MenuItem"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1137 memset( &info, 0, sizeof info );
1139 info.cbSize = sizeof(MENUITEMINFO);
1140 info.fMask = MIIM_STRING | MIIM_ID;
1141 info.dwTypeData = strback;
1142 info.cch = sizeof(strback);
1144 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub2, FALSE, &info);
1145 ok (rc, "Getting the menus info failed\n");
1146 ok (info.wID == (UINT)hmenuSub2, "IDs differ for popup menu\n");
1147 ok (!strcmp(info.dwTypeData, "Submenu2"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1152 register_menu_check_class();
1154 test_menu_locked_by_window();
1155 test_menu_ownerdraw();
1156 test_menu_add_string();
1157 test_menu_iteminfo();
1158 test_menu_search_bycommand();