| /* |
| * Win32 user functions |
| * |
| * Copyright 1995 Martin von Loewis |
| */ |
| |
| /* This file contains only wrappers to existing Wine functions or trivial |
| stubs. 'Real' implementations go into context specific files */ |
| |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <stdarg.h> |
| #include "windows.h" |
| #include "winerror.h" |
| #include "relay32.h" |
| #include "alias.h" |
| #include "stackframe.h" |
| #include "xmalloc.h" |
| #include "handle32.h" |
| #include "struct32.h" |
| #include "resource32.h" |
| #include "string32.h" |
| #include "dialog.h" |
| #include "win.h" |
| #include "debug.h" |
| #include "stddebug.h" |
| |
| /*********************************************************************** |
| * RegisterClassA (USER32.426) |
| */ |
| ATOM USER32_RegisterClassA(WNDCLASSA* wndclass) |
| { |
| WNDCLASS copy; |
| HANDLE classh = 0, menuh = 0; |
| SEGPTR classsegp, menusegp; |
| char *classbuf, *menubuf; |
| |
| ATOM retval; |
| copy.style=wndclass->style; |
| ALIAS_RegisterAlias(0,0,(DWORD)wndclass->lpfnWndProc); |
| copy.lpfnWndProc=wndclass->lpfnWndProc; |
| copy.cbClsExtra=wndclass->cbClsExtra; |
| copy.cbWndExtra=wndclass->cbWndExtra; |
| copy.hInstance=(HINSTANCE)wndclass->hInstance; |
| copy.hIcon=(HICON)wndclass->hIcon; |
| copy.hCursor=(HCURSOR)wndclass->hCursor; |
| copy.hbrBackground=(HBRUSH)wndclass->hbrBackground; |
| |
| /* FIXME: There has to be a better way of doing this - but neither |
| malloc nor alloca will work */ |
| |
| if(wndclass->lpszMenuName) |
| { |
| menuh = GlobalAlloc(0, strlen(wndclass->lpszMenuName)+1); |
| menusegp = WIN16_GlobalLock(menuh); |
| menubuf = PTR_SEG_TO_LIN(menusegp); |
| strcpy( menubuf, wndclass->lpszMenuName); |
| copy.lpszMenuName=menusegp; |
| }else |
| copy.lpszMenuName=0; |
| if(wndclass->lpszClassName) |
| { |
| classh = GlobalAlloc(0, strlen(wndclass->lpszClassName)+1); |
| classsegp = WIN16_GlobalLock(classh); |
| classbuf = PTR_SEG_TO_LIN(classsegp); |
| strcpy( classbuf, wndclass->lpszClassName); |
| copy.lpszClassName=classsegp; |
| } |
| retval = RegisterClass(©); |
| GlobalFree(menuh); |
| GlobalFree(classh); |
| return retval; |
| } |
| |
| /*********************************************************************** |
| * GetMessageA (USER32.269) |
| */ |
| BOOL USER32_GetMessageA(MSG32* lpmsg,DWORD hwnd,DWORD min,DWORD max) |
| { |
| BOOL ret; |
| MSG msg; |
| ret=GetMessage(MAKE_SEGPTR(&msg),(HWND)hwnd,min,max); |
| STRUCT32_MSG16to32(&msg,lpmsg); |
| return ret; |
| } |
| |
| /*********************************************************************** |
| * BeginPaint (USER32.9) |
| */ |
| HDC USER32_BeginPaint(DWORD hwnd,PAINTSTRUCT32 *lpps) |
| { |
| PAINTSTRUCT ps; |
| HDC ret; |
| ret=BeginPaint((HWND)hwnd,&ps); |
| lpps->hdc=(DWORD)ps.hdc; |
| lpps->fErase=ps.fErase; |
| lpps->rcPaint.top=ps.rcPaint.top; |
| lpps->rcPaint.left=ps.rcPaint.left; |
| lpps->rcPaint.right=ps.rcPaint.right; |
| lpps->rcPaint.bottom=ps.rcPaint.bottom; |
| lpps->fRestore=ps.fRestore; |
| lpps->fIncUpdate=ps.fIncUpdate; |
| return ret; |
| } |
| |
| /*********************************************************************** |
| * EndPaint (USER32.175) |
| */ |
| BOOL USER32_EndPaint(DWORD hwnd,PAINTSTRUCT32 *lpps) |
| { |
| PAINTSTRUCT ps; |
| ps.hdc=(HDC)lpps->hdc; |
| ps.fErase=lpps->fErase; |
| ps.rcPaint.top=lpps->rcPaint.top; |
| ps.rcPaint.left=lpps->rcPaint.left; |
| ps.rcPaint.right=lpps->rcPaint.right; |
| ps.rcPaint.bottom=lpps->rcPaint.bottom; |
| ps.fRestore=lpps->fRestore; |
| ps.fIncUpdate=lpps->fIncUpdate; |
| EndPaint((HWND)hwnd,&ps); |
| return TRUE; |
| } |
| |
| /*********************************************************************** |
| * DispatchMessageA (USER32.140) |
| */ |
| LONG USER32_DispatchMessageA(MSG32* lpmsg) |
| { |
| MSG msg; |
| LONG ret; |
| STRUCT32_MSG32to16(lpmsg,&msg); |
| ret=DispatchMessage(&msg); |
| STRUCT32_MSG16to32(&msg,lpmsg); |
| return ret; |
| } |
| |
| /*********************************************************************** |
| * TranslateMessage (USER32.555) |
| */ |
| BOOL USER32_TranslateMessage(MSG32* lpmsg) |
| { |
| MSG msg; |
| STRUCT32_MSG32to16(lpmsg,&msg); |
| return TranslateMessage(&msg); |
| } |
| |
| /*********************************************************************** |
| * CreateWindowExA (USER32.82) |
| */ |
| DWORD USER32_CreateWindowExA(long flags,char* class,char *title, |
| long style,int x,int y,int width,int height,DWORD parent,DWORD menu, |
| DWORD instance,DWORD param) |
| { |
| DWORD retval; |
| HANDLE classh=0, titleh=0; |
| SEGPTR classsegp=0, titlesegp=0; |
| char *classbuf, *titlebuf; |
| int usec,uset; |
| |
| /*Have to translate CW_USEDEFAULT */ |
| if(x==CW_USEDEFAULT32)x=CW_USEDEFAULT; |
| if(y==CW_USEDEFAULT32)y=CW_USEDEFAULT; |
| if(width==CW_USEDEFAULT32)width=CW_USEDEFAULT; |
| if(height==CW_USEDEFAULT32)height=CW_USEDEFAULT; |
| |
| /* FIXME: There has to be a better way of doing this - but neither |
| malloc nor alloca will work */ |
| usec = HIWORD(class); |
| uset = HIWORD(title); |
| |
| if(usec){ |
| classh = GlobalAlloc(0, strlen(class)+1); |
| classsegp = WIN16_GlobalLock(classh); |
| classbuf = PTR_SEG_TO_LIN(classsegp); |
| strcpy( classbuf, class ); |
| } |
| if(uset){ |
| titleh = GlobalAlloc(0, strlen(title)+1); |
| titlesegp = WIN16_GlobalLock(titleh); |
| titlebuf = PTR_SEG_TO_LIN(titlesegp); |
| strcpy( titlebuf, title ); |
| } |
| |
| retval = (DWORD) CreateWindowEx(flags,(usec ? classsegp : (SEGPTR)class), |
| (uset ? titlesegp : (SEGPTR)title),style,x,y,width,height, |
| (HWND)parent,(HMENU)menu,(HINSTANCE)instance, |
| (DWORD)param); |
| if(usec)GlobalFree(classh); |
| if(uset)GlobalFree(titleh); |
| return retval; |
| } |
| |
| DWORD USER32_CreateWindowExW(long flags,LPCWSTR class,LPCWSTR title, |
| long style,int x,int y,int width,int height,DWORD parent,DWORD menu, |
| DWORD instance,DWORD param) |
| { |
| HWND hwnd; |
| LPSTR c,t; |
| int usec,uset; |
| usec=HIWORD(class); |
| uset=HIWORD(title); |
| c = usec ? STRING32_DupUniToAnsi(class) : (LPSTR)class; |
| t = uset ? STRING32_DupUniToAnsi(title) : (LPSTR)title; |
| hwnd=USER32_CreateWindowExA(flags,c,t,style,x,y,width,height,parent,menu, |
| instance,param); |
| if(usec)free(c); |
| if(uset)free(t); |
| return hwnd; |
| } |
| |
| /*********************************************************************** |
| * InvalidateRect (USER32.327) |
| */ |
| BOOL USER32_InvalidateRect(HWND hWnd,const RECT32 *lpRect,BOOL bErase) |
| { |
| RECT r; |
| |
| if (lpRect == NULL) |
| InvalidateRect(hWnd, (RECT *)NULL, bErase); |
| else { |
| STRUCT32_RECT32to16(lpRect,&r); |
| InvalidateRect(hWnd,&r,bErase); |
| } |
| /* FIXME: Return meaningful value */ |
| return TRUE; |
| } |
| |
| /*********************************************************************** |
| * DrawTextA (USER32.163) |
| */ |
| int USER32_DrawTextA(HDC hdc,LPCSTR lpStr,int count,RECT32* r32,UINT uFormat) |
| { |
| RECT r; |
| STRUCT32_RECT32to16(r32,&r); |
| return DrawText(hdc,lpStr,count,&r,uFormat); |
| } |
| |
| /*********************************************************************** |
| * GetClientRect (USER32.219) |
| */ |
| BOOL USER32_GetClientRect(HWND hwnd,RECT32 *r32) |
| { |
| RECT r; |
| GetClientRect(hwnd,&r); |
| STRUCT32_RECT16to32(&r,r32); |
| /* FIXME: return value */ |
| return 0; |
| } |
| |
| UINT USER32_SetTimer(HWND hwnd, UINT id, UINT timeout, void *proc) |
| |
| { |
| dprintf_win32(stddeb, "USER32_SetTimer: %d %d %d %08lx\n", hwnd, id, timeout, |
| (LONG)proc ); |
| return SetTimer( hwnd, id, timeout, MAKE_SEGPTR(proc)); |
| } |
| |
| /* WARNING: It has not been verified that the signature or semantics |
| of the corresponding NT function is the same */ |
| |
| HWND USER32_CreateDialogIndirectParamAorW(HINSTANCE hInst,LPVOID templ, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam,int A) |
| { |
| DLGTEMPLATE32 *dlgTempl=templ; |
| DLGITEMTEMPLATE32 *dlgitem; |
| WORD *ptr; |
| DWORD MenuName=0; |
| DWORD ClassName=0; |
| DWORD szFontName=0; |
| WORD wPointSize; |
| HFONT hFont=0; |
| HMENU hMenu=0; |
| DWORD exStyle; |
| DWORD szCaption; |
| RECT rect; |
| DIALOGINFO *dlgInfo; |
| WND *wndPtr; |
| WORD xUnit = xBaseUnit; |
| WORD yUnit = yBaseUnit; |
| int i; |
| DWORD ClassId; |
| DWORD Text; |
| HWND hwnd,hwndCtrl; |
| HWND hwndDefButton=0; |
| WCHAR buffer[200]; |
| |
| /* parse the dialog template header*/ |
| exStyle = dlgTempl->dwExtendedStyle; |
| ptr = (WORD*)(dlgTempl+1); |
| switch(*ptr){ |
| case 0: MenuName=0;ptr++;break; |
| case 0xFFFF: MenuName=*(ptr+1);ptr+=2;break; |
| default: MenuName = (DWORD)ptr; |
| ptr += STRING32_lstrlenW(ptr)+1; |
| } |
| switch(*ptr){ |
| case 0: ClassName = DIALOG_CLASS_ATOM;ptr++;break; |
| case 0xFFFF: ClassName = *(ptr+1);ptr+=2;break; |
| default: ClassName = (DWORD)ptr; |
| ptr += STRING32_lstrlenW(ptr)+1; |
| } |
| szCaption=(DWORD)ptr; |
| ptr+=STRING32_lstrlenW(ptr)+1; |
| if(dlgTempl->style & DS_SETFONT) |
| { |
| wPointSize = *ptr; |
| ptr++; |
| szFontName = (DWORD)ptr; |
| ptr+=STRING32_lstrlenW(ptr)+1; |
| } |
| |
| if(MenuName) hMenu=WIN32_LoadMenuW(hInst,(LPWSTR)MenuName); |
| if(dlgTempl->style & DS_SETFONT) |
| { |
| fprintf(stderr,"Win32: dialog fonts not supported yet\n"); |
| } |
| |
| /* Create dialog main window */ |
| rect.left = rect.top = 0; |
| rect.right = dlgTempl->cx * xUnit / 4; |
| rect.bottom = dlgTempl->cy * yUnit / 8; |
| |
| /* FIXME: proper modalframe handling ??*/ |
| if (dlgTempl->style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME; |
| |
| AdjustWindowRectEx( &rect, dlgTempl->style, |
| hMenu ? TRUE : FALSE , exStyle ); |
| rect.right -= rect.left; |
| rect.bottom -= rect.top; |
| |
| if(dlgTempl->x == CW_USEDEFAULT) |
| rect.left = rect.top = CW_USEDEFAULT; |
| else{ |
| rect.left += dlgTempl->x * xUnit / 4; |
| rect.top += dlgTempl->y * yUnit / 8; |
| if (!(dlgTempl->style & DS_ABSALIGN)) |
| ClientToScreen(hWndParent, (POINT *)&rect ); |
| } |
| |
| /* FIXME: Here is the place to consider A */ |
| hwnd = USER32_CreateWindowExW(exStyle, (LPWSTR)ClassName, (LPWSTR)szCaption, |
| dlgTempl->style & ~WS_VISIBLE, |
| rect.left, rect.top, rect.right, rect.bottom, |
| hWndParent, hMenu, hInst, 0); |
| |
| if(!hwnd) |
| { |
| if(hFont)DeleteObject(hFont); |
| if(hMenu)DeleteObject(hMenu); |
| return 0; |
| } |
| |
| wndPtr = WIN_FindWndPtr(hwnd); |
| |
| /* FIXME: should purge junk from system menu, but windows/dialog.c |
| says this does not belong here */ |
| |
| /* Create control windows */ |
| dprintf_dialog(stddeb, " BEGIN\n" ); |
| dlgInfo = (DIALOGINFO *)wndPtr->wExtra; |
| dlgInfo->msgResult = 0; /* This is used to store the default button id */ |
| dlgInfo->hDialogHeap = 0; |
| |
| for (i = 0; i < dlgTempl->noOfItems; i++) |
| { |
| if((int)ptr&3) |
| { |
| fprintf(stddeb,"DWORD aligning\n"); |
| ptr++; |
| } |
| dlgitem = (DLGITEMTEMPLATE32*)ptr; |
| ptr = (WORD*)(dlgitem+1); |
| if(*ptr == 0xFFFF) { |
| /* FIXME: ignore HIBYTE? */ |
| ClassId = *(ptr+1); |
| ptr+=2; |
| }else{ |
| ClassId = (DWORD)ptr; |
| ptr += STRING32_lstrlenW(ptr)+1; |
| } |
| if(*ptr == 0xFFFF) { |
| Text = *(ptr+1); |
| ptr+=2; |
| }else{ |
| Text = (DWORD)ptr; |
| ptr += STRING32_lstrlenW(ptr)+1; |
| } |
| if(!HIWORD(ClassId)) |
| { |
| switch(LOWORD(ClassId)) |
| { |
| case 0x80: STRING32_AnsiToUni(buffer,"BUTTON" ); break; |
| case 0x81: STRING32_AnsiToUni( buffer, "EDIT" ); break; |
| case 0x82: STRING32_AnsiToUni( buffer, "STATIC" ); break; |
| case 0x83: STRING32_AnsiToUni( buffer, "LISTBOX" ); break; |
| case 0x84: STRING32_AnsiToUni( buffer, "SCROLLBAR" ); break; |
| case 0x85: STRING32_AnsiToUni( buffer, "COMBOBOX" ); break; |
| default: buffer[0] = '\0'; break; |
| } |
| ClassId = (DWORD)buffer; |
| } |
| /*FIXME: debugging output*/ |
| /*FIXME: local edit ?*/ |
| exStyle = dlgitem->dwExtendedStyle|WS_EX_NOPARENTNOTIFY; |
| if(*ptr) |
| { |
| fprintf(stderr,"having data\n"); |
| } |
| ptr++; |
| hwndCtrl = USER32_CreateWindowExW(WS_EX_NOPARENTNOTIFY, |
| (LPWSTR)ClassId, (LPWSTR)Text, |
| dlgitem->style | WS_CHILD, |
| dlgitem->x * xUnit / 4, |
| dlgitem->y * yUnit / 8, |
| dlgitem->cx * xUnit / 4, |
| dlgitem->cy * yUnit / 8, |
| hwnd, (HMENU)((DWORD)dlgitem->id), |
| hInst, (SEGPTR)0 ); |
| SetWindowPos( hwndCtrl, HWND_BOTTOM, 0, 0, 0, 0, |
| SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); |
| /* Send initialisation messages to the control */ |
| if (hFont) SendMessage( hwndCtrl, WM_SETFONT, (WPARAM)hFont, 0 ); |
| if (SendMessage( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON) |
| { |
| /* If there's already a default push-button, set it back */ |
| /* to normal and use this one instead. */ |
| if (hwndDefButton) |
| SendMessage( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON, FALSE); |
| hwndDefButton = hwndCtrl; |
| dlgInfo->msgResult = GetWindowWord( hwndCtrl, GWW_ID ); |
| } |
| } |
| dprintf_dialog(stddeb, " END\n" ); |
| |
| /* Initialise dialog extra data */ |
| ALIAS_RegisterAlias(0,0,lpDialogFunc); |
| dlgInfo->dlgProc = lpDialogFunc; |
| dlgInfo->hUserFont = hFont; |
| dlgInfo->hMenu = hMenu; |
| dlgInfo->xBaseUnit = xUnit; |
| dlgInfo->yBaseUnit = yUnit; |
| dlgInfo->hwndFocus = DIALOG_GetFirstTabItem( hwnd ); |
| |
| /* Send initialisation messages and set focus */ |
| if (dlgInfo->hUserFont) |
| SendMessage( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 ); |
| if (SendMessage( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, dwInitParam )) |
| SetFocus( dlgInfo->hwndFocus ); |
| if (dlgTempl->style & WS_VISIBLE) ShowWindow(hwnd, SW_SHOW); |
| return hwnd; |
| } |
| |
| HWND USER32_CreateDialogIndirectParamW(HINSTANCE hInst,LPVOID dlgTempl, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam) |
| { |
| return USER32_CreateDialogIndirectParamAorW(hInst,dlgTempl,hWndParent, |
| lpDialogFunc,dwInitParam,0); |
| } |
| |
| HWND USER32_CreateDialogIndirectParamA(HINSTANCE hInst,LPVOID dlgTempl, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam) |
| { |
| return USER32_CreateDialogIndirectParamAorW(hInst,dlgTempl,hWndParent, |
| lpDialogFunc,dwInitParam,1); |
| } |
| |
| HWND USER32_CreateDialogParamW(HINSTANCE hInst,LPCWSTR lpszName, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam) |
| { |
| HANDLE32 hrsrc; |
| hrsrc=FindResource32(hInst,lpszName,(LPWSTR)RT_DIALOG); |
| if(!hrsrc)return 0; |
| return USER32_CreateDialogIndirectParamW(hInst, |
| LoadResource32(hInst, hrsrc),hWndParent,lpDialogFunc,dwInitParam); |
| } |
| |
| HWND USER32_CreateDialogParamA(HINSTANCE hInst,LPCSTR lpszName, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam) |
| { |
| HWND res; |
| if(!HIWORD(lpszName)) |
| res = USER32_CreateDialogParamW(hInst,(LPCWSTR)lpszName,hWndParent, |
| lpDialogFunc,dwInitParam); |
| else{ |
| LPWSTR uni=STRING32_DupAnsiToUni(lpszName); |
| res=USER32_CreateDialogParamW(hInst,uni,hWndParent, |
| lpDialogFunc,dwInitParam); |
| } |
| return res; |
| } |
| |
| int USER32_DialogBoxIndirectParamW(HINSTANCE hInstance,LPVOID dlgTempl, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam) |
| { |
| HWND hwnd; |
| hwnd = USER32_CreateDialogIndirectParamW(hInstance,dlgTempl, |
| hWndParent,lpDialogFunc,dwInitParam); |
| if(hwnd)return DIALOG_DoDialogBox(hwnd,hWndParent); |
| return -1; |
| } |
| |
| int USER32_DialogBoxIndirectParamA(HINSTANCE hInstance,LPVOID dlgTempl, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam) |
| { |
| HWND hwnd; |
| hwnd = USER32_CreateDialogIndirectParamA(hInstance,dlgTempl, |
| hWndParent,lpDialogFunc,dwInitParam); |
| if(hwnd)return DIALOG_DoDialogBox(hwnd,hWndParent); |
| return -1; |
| } |
| |
| int USER32_DialogBoxParamW(HINSTANCE hInstance,LPCWSTR lpszName, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam) |
| { |
| HWND hwnd; |
| hwnd = USER32_CreateDialogParamW(hInstance,lpszName, |
| hWndParent,lpDialogFunc,dwInitParam); |
| if(hwnd)return DIALOG_DoDialogBox(hwnd,hWndParent); |
| return -1; |
| } |
| |
| int USER32_DialogBoxParamA(HINSTANCE hInstance,LPCSTR lpszName, |
| HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam) |
| { |
| HWND hwnd; |
| hwnd = USER32_CreateDialogParamA(hInstance,lpszName, |
| hWndParent,lpDialogFunc,dwInitParam); |
| if(hwnd)return DIALOG_DoDialogBox(hwnd,hWndParent); |
| return -1; |
| } |
| |
| int USER32_wsprintfA( int *args ) |
| { |
| return vsprintf( (char *)args[0], (char *)args[1], (va_list)&args[2] ); |
| } |