Skip to content
Snippets Groups Projects
Commit d18872de authored by Alexandre Julliard's avatar Alexandre Julliard
Browse files

Release 940510

May 9, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [controls/scroll.c]
	Make thumbtrack button disappear if scroll box ratio < 3:1.
	Make arrow buttons rectangular if scroll box ratio < 2:1.
	Add code for SBS_TOPALIGN, SBS_BOTTOMALIGN, 
				SBS_LEFTALIGN & SBS_RIGHTALIGN.
	Bug fix in NC_CreateScrollBars(), no more bigbutt in calendar.exe... :-)

	* [loader/library.c] [loader/task.c] [misc/exec.c]
	Continue playing around trying to get a second task running.

	* [windows/mdi.c]
	Change OBM_CLOSE for OBM_OLD_CLOSE, a smaller dot button when maximized.

	* [everywhere]
	Adding previous works of the Apr 25, 94.

Tue May 10 18:09:14 1994 Erik Bos (erik@trashcan.hacktic.nl)

	* [if1632/mmsystem.spec] [misc/mmsystem.c] [include/mmsystem.h]
	Added Martin's mmsystem.dll stubs.

	* [misc/sound.c]
	Added remaining stubs for sound.dll.

	* [if1632/shell.spec] [misc/shell.c]
	Fixed prototypes (I found them in BC 4) and added ShellAbout()
	and AboutDlgProc().
parent 1d62f6b9
No related branches found
No related tags found
No related merge requests found
----------------------------------------------------------------------
May 9, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [controls/scroll.c]
Make thumbtrack button disappear if scroll box ratio < 3:1.
Make arrow buttons rectangular if scroll box ratio < 2:1.
Add code for SBS_TOPALIGN, SBS_BOTTOMALIGN,
SBS_LEFTALIGN & SBS_RIGHTALIGN.
Bug fix in NC_CreateScrollBars(), no more bigbutt in calendar.exe... :-)
* [loader/library.c] [loader/task.c] [misc/exec.c]
Continue playing around trying to get a second task running.
* [windows/mdi.c]
Change OBM_CLOSE for OBM_OLD_CLOSE, a smaller dot button when maximized.
* [everywhere]
Adding previous works of the Apr 25, 94.
Tue May 10 18:09:14 1994 Erik Bos (erik@trashcan.hacktic.nl)
* [if1632/mmsystem.spec] [misc/mmsystem.c] [include/mmsystem.h]
Added Martin's mmsystem.dll stubs.
* [misc/sound.c]
Added remaining stubs for sound.dll.
* [if1632/shell.spec] [misc/shell.c]
Fixed prototypes (I found them in BC 4) and added ShellAbout()
and AboutDlgProc().
----------------------------------------------------------------------
May 1, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
......@@ -39,7 +70,42 @@ Wed Apr 20 23:58:58 1994 Scott A. Laird (scott@curly)
path when given a simple file name. Fixed GetSetProfile to allow
enumerating all key names when KeyName is null.
Apr 25, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [objects/bitblt.c]
Add protection to BitBlt() & StretchBlt() for width or height = 0.
* [windows/nonclient.c]
Avoid painting in NC_DoNCPaint() if IsWindowVisible().
Simplify NC_TrackMouseMenuBar() because code moved to MenuFocusLoop().
* [windows/win.c]
CreateWindowEx() & DestroyWindow() now call respectively
AddWindowToTask() & RemoveWindowFromTask().
New empty stub for function AnyPopup().
* [loader/library.c]
Bug Fix : GetModuleFileName() now return full path filename.
* [include/menu.h] [controls/menu.c]
Add hText handle and remove obsolete MENUITEM struct members.
Add a ReleaseCapture() in SetMenu() when menubar changed while captured.
Add MenuMouseMove() MenuButtonUp() in function MenuFocusLoop().
* [misc/file.c]
GetTempFilename() now create a file.
_lcreate() use unix open (name, mode, perm), with perm=O666.
* [if1632/relay.c]
Remove temporarly builtin SHELL.DLL, Add MMSYSTEM.DLL in builtin list.
* New file [misc/mmsystem.c]
* New file [include/mmsystem.h]
* New file [if1632/mmsystem.spec]
Many, many empty stubs ... :-)
----------------------------------------------------------------------
Wed Apr 20 14:53:35 1994 Bob Amstadt (bob@pooh)
* [tools/build.c] [if1632/call.S] [if1632/Imakefile]
......@@ -68,8 +134,6 @@ Apr 18, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
Move functions GetWindowTask(), GetNumTask(), EnumTaskWindows()
from 'loader/library.c'.
* [loader/library.c]
* [if1632/user.c] [if1632/kernel.c]
Put Atoms functions entries.
......
#include "autoconf.h"
#include "Wine.tmpl"
#if defined(i386FreeBsd)
#if defined(i386FreeBsd) || defined(FreeBSDArchitecture)
MAKE = gmake
CC = gcc -D__FreeBSD__
#endif
......@@ -77,7 +77,7 @@ OBJS = $(COMMONOBJS) $(LIBOBJS)
#ifdef i386BsdArchitecture
SYSLIBS = -ll -lm -li386 -lgnumalloc
#endif
#ifdef i386FreeBsd
#if defined(i386FreeBsd) || defined(FreeBSDArchitecture)
SYSLIBS = -ll -lm -lgnumalloc
#endif
#ifdef LinuxArchitecture
......
......@@ -171,6 +171,12 @@ bob@amscons.com
7. WHAT'S NEW
WHAT'S NEW with Wine-940510: (see ChangeLog for details)
- debugger improvements
- mmsystem
- ShellAbout() and AboutDlgProc()
- and many many bug fixes!
WHAT'S NEW with Wine-940505: (see ChangeLog for details)
- faster color_stretch()
- SetSysMenu(), GetCursor(), GetDesktopWindow()
......
......@@ -5,6 +5,7 @@
*
*/
#define DEBUG_COMBO
/*
#define DEBUG_COMBO
*/
......@@ -66,7 +67,8 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
if (wndPtr->dwStyle & CBS_SIMPLE)
lphc->hWndEdit = CreateWindow("EDIT", "",
/* lphc->hWndEdit = CreateWindow("EDIT", "", */
lphc->hWndEdit = CreateWindow("STATIC", "",
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | SS_LEFT,
0, 0, width - bm.bmHeight, bm.bmHeight,
hwnd, 1, wndPtr->hInstance, 0L);
......@@ -114,7 +116,7 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
y = SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L);
if (y != LB_ERR) {
SendMessage(lphc->hWndLBox, LB_GETTEXT, (WORD)y, (LPARAM)str);
SendMessage(lphc->hWndEdit, WM_SETTEXT, (WORD)y, (LPARAM)str);
SendMessage(lphc->hWndEdit, WM_SETTEXT, (WORD)y, (LPARAM)str);
}
SendMessage(GetParent(hwnd), WM_COMMAND, wndPtr->wIDmenu,
MAKELONG(hwnd, CBN_SELCHANGE));
......@@ -136,20 +138,26 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
ReleaseDC(hwnd, hDC);
wndPtr = WIN_FindWndPtr(hwnd);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
lphc->dwState = lphc->dwState ^ CB_SHOWDROPDOWN;
if ((lphc->dwState & CB_SHOWDROPDOWN) == CB_SHOWDROPDOWN) {
ShowWindow(lphc->hWndLBox, SW_SHOW);
SetFocus(lphc->hWndLBox);
}
else {
SetFocus(lphc->hWndEdit);
printf("before Combo Restore Focus !\n");
SetFocus(lphc->hWndEdit);
printf("before Combo List Hide !\n");
ShowWindow(lphc->hWndLBox, SW_HIDE);
printf("before Combo List GetCurSel !\n");
y = SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L);
if (y != LB_ERR) {
printf("before Combo List GetText !\n");
SendMessage(lphc->hWndLBox, LB_GETTEXT, (WORD)y, (LPARAM)str);
SendMessage(lphc->hWndEdit, WM_SETTEXT, (WORD)y, (LPARAM)str);
}
printf("End of Combo List Hide !\n");
}
}
break;
case WM_LBUTTONUP:
printf("Combo WM_LBUTTONUP wParam=%x lParam=%lX !\n", wParam, lParam);
......@@ -163,6 +171,7 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
case WM_KEYDOWN:
wndPtr = WIN_FindWndPtr(hwnd);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
y = SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L);
count = SendMessage(lphc->hWndLBox, LB_GETCOUNT, 0, 0L);
printf("COMBOBOX // GetKeyState(VK_MENU)=%d\n", GetKeyState(VK_MENU));
......@@ -214,13 +223,16 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
GetClientRect(hwnd, &rect);
hDC = BeginPaint(hwnd, &paintstruct);
hMemDC = CreateCompatibleDC(hDC);
GetObject(hComboBit, sizeof(BITMAP), (LPSTR)&bm);
SelectObject(hMemDC, hComboBit);
BitBlt(hDC, rect.right - bm.bmWidth, 0,
bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
if (hMemDC != 0 && hComboBit != 0) {
GetObject(hComboBit, sizeof(BITMAP), (LPSTR)&bm);
SelectObject(hMemDC, hComboBit);
BitBlt(hDC, rect.right - bm.bmWidth, 0,
bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
}
DeleteDC(hMemDC);
EndPaint(hwnd, &paintstruct);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
InvalidateRect(lphc->hWndEdit, NULL, TRUE);
UpdateWindow(lphc->hWndEdit);
if ((lphc->dwState & CB_SHOWDROPDOWN) == CB_SHOWDROPDOWN) {
......@@ -230,10 +242,12 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
break;
case WM_SETFOCUS:
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
SetFocus(lphc->hWndEdit);
break;
case WM_KILLFOCUS:
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
ShowWindow(lphc->hWndLBox, SW_HIDE);
y = SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L);
if (y != LB_ERR) {
......@@ -246,62 +260,76 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
printf("CB_ADDSTRING '%s' !\n", (LPSTR)lParam);
#endif
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_ADDSTRING, wParam, lParam));
case CB_GETLBTEXT:
printf("CB_GETLBTEXT #%u !\n", wParam);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_GETTEXT, wParam, lParam));
case CB_GETLBTEXTLEN:
printf("CB_GETLBTEXTLEN !\n");
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_GETTEXTLEN, wParam, lParam));
case CB_INSERTSTRING:
printf("CB_INSERTSTRING '%s' !\n", (LPSTR)lParam);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam));
case CB_DELETESTRING:
printf("CB_DELETESTRING #%u !\n", wParam);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_DELETESTRING, wParam, 0L));
case CB_RESETCONTENT:
printf("CB_RESETCONTENT !\n");
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_RESETCONTENT, 0, 0L));
case CB_DIR:
printf("ComboBox CB_DIR !\n");
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_DIR, wParam, lParam));
case CB_FINDSTRING:
lphc = ComboGetStorageHeader(hwnd);
return(SendMessage(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam));
case CB_GETCOUNT:
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_GETCOUNT, 0, 0L));
case CB_GETCURSEL:
printf("ComboBox CB_GETCURSEL !\n");
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L));
case CB_SETCURSEL:
printf("ComboBox CB_SETCURSEL wParam=%X !\n", wParam);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_SETCURSEL, wParam, 0L));
case CB_GETEDITSEL:
printf("ComboBox CB_GETEDITSEL !\n");
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
/* return(SendMessage(lphc->hWndEdit, EM_GETSEL, 0, 0L)); */
break;
case CB_SETEDITSEL:
printf("ComboBox CB_SETEDITSEL lParam=%lX !\n", lParam);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
/* return(SendMessage(lphc->hWndEdit, EM_SETSEL, 0, lParam)); */
break;
case CB_SELECTSTRING:
printf("ComboBox CB_SELECTSTRING !\n");
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
break;
case CB_SHOWDROPDOWN:
printf("ComboBox CB_SHOWDROPDOWN !\n");
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
lphc->dwState = lphc->dwState | CB_SHOWDROPDOWN;
if (wParam != 0) {
ShowWindow(lphc->hWndLBox, SW_SHOW);
......@@ -316,16 +344,19 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
case CB_GETITEMDATA:
printf("ComboBox CB_GETITEMDATA wParam=%X !\n", wParam);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0L));
break;
case CB_SETITEMDATA:
printf("ComboBox CB_SETITEMDATA wParam=%X lParam=%lX !\n", wParam, lParam);
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
return(SendMessage(lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam));
break;
case CB_LIMITTEXT:
printf("ComboBox CB_LIMITTEXT !\n");
lphc = ComboGetStorageHeader(hwnd);
if (lphc == NULL) return 0;
/* return(SendMessage(lphc->hWndEdit, EM_LIMITTEXT, wParam, 0L)); */
break;
......@@ -390,6 +421,7 @@ int DlgDirListComboBox(HWND hDlg, LPSTR lpPathSpec,
hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
hWnd = GetDlgItem(hDlg, nIDLBox);
lphc = ComboGetStorageHeader(hWnd);
if (lphc == NULL) return 0;
SendMessage(lphc->hWndLBox, LB_RESETCONTENT, 0, 0L);
return SendMessage(lphc->hWndLBox, LB_DIR, wType, (DWORD)lpPathSpec);
}
......
......@@ -72,6 +72,7 @@ LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
#ifdef DEBUG_LISTBOX
printf("ListBox WM_CREATE %lX !\n", lphl);
#endif
if (lphl == NULL) return 0;
createStruct = (CREATESTRUCT *)lParam;
if (HIWORD(createStruct->lpCreateParams) != 0)
lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
......@@ -91,7 +92,7 @@ LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
return 0;
case WM_DESTROY:
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == 0) return 0;
if (lphl == NULL) return 0;
ListBoxResetContent(hwnd);
free(lphl);
*((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
......@@ -189,7 +190,7 @@ LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
SetFocus(hwnd);
SetCapture(hwnd);
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
if (lphl == NULL) return 0;
lphl->PrevFocused = lphl->ItemFocused;
y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
......@@ -225,6 +226,7 @@ LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
y = HIWORD(lParam);
if (y < 4) {
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return 0;
if (lphl->FirstVisible > 1) {
lphl->FirstVisible--;
if (wndPtr->dwStyle & WS_VSCROLL)
......@@ -237,6 +239,7 @@ LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
GetClientRect(hwnd, &rect);
if (y > (rect.bottom - 4)) {
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return 0;
if (lphl->FirstVisible < lphl->ItemsCount) {
lphl->FirstVisible++;
if (wndPtr->dwStyle & WS_VSCROLL)
......@@ -248,6 +251,8 @@ LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
}
if ((y > 0) && (y < (rect.bottom - 4))) {
if ((y < rectsel.top) || (y > rectsel.bottom)) {
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return 0;
wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
lphl->ItemFocused = wRet;
......@@ -722,7 +727,10 @@ void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)
MEASUREITEMSTRUCT *measure;
HANDLE hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(MEASUREITEMSTRUCT));
measure = (MEASUREITEMSTRUCT *) USER_HEAP_ADDR(hTemp);
if (measure == NULL) return;
if (measure == NULL) {
printf("ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
return;
}
measure->CtlType = ODT_LISTBOX;
measure->CtlID = wndPtr->wIDmenu;
measure->itemID = lpls->dis.itemID;
......@@ -747,6 +755,10 @@ int ListBoxAddString(HWND hwnd, LPSTR newstr)
if (lphl == NULL) return LB_ERR;
hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LISTSTRUCT));
lplsnew = (LPLISTSTRUCT) USER_HEAP_ADDR(hTemp);
if (lplsnew == NULL) {
printf("ListBoxAddString() // Bad allocation of new item !\n");
return LB_ERRSPACE;
}
lpls = lphl->lpFirst;
if (lpls != NULL) {
while(lpls->lpNext != NULL) {
......@@ -822,6 +834,10 @@ int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
}
hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LISTSTRUCT));
lplsnew = (LPLISTSTRUCT) USER_HEAP_ADDR(hTemp);
if (lplsnew == NULL) {
printf("ListBoxAddString() // Bad allocation of new item !\n");
return LB_ERRSPACE;
}
ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
lplsnew->hMem = hTemp;
lpls->lpNext = lplsnew;
......@@ -981,9 +997,8 @@ int ListBoxResetContent(HWND hwnd)
lphl->ItemFocused = 0;
lphl->PrevFocused = 0;
if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
SendMessage(wndPtr->hwndParent, WM_COMMAND,
SendMessage(lphl->hWndLogicParent, WM_COMMAND,
wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
if (wndPtr->dwStyle & WS_VSCROLL)
SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
......@@ -1007,7 +1022,7 @@ int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
UINT i;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
lphl->ItemFocused = LB_ERR;
lphl->ItemFocused = LB_ERR;
if (wIndex >= lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
......@@ -1023,7 +1038,7 @@ int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
}
lphl->ItemFocused = wIndex;
if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
SendMessage(wndPtr->hwndParent, WM_COMMAND,
SendMessage(lphl->hWndLogicParent, WM_COMMAND,
wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
return LB_ERR;
}
......@@ -1183,6 +1198,10 @@ int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
LPHEADLIST lphl, LPLISTSTRUCT lpls)
{
RECT rect;
if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
printf("ListBoxDefaultItem() // Bad Pointers !\n");
return FALSE;
}
GetClientRect(hwnd, &rect);
SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
lpls->dis.CtlType = lphl->DrawCtlType;
......@@ -1193,6 +1212,7 @@ int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
lpls->dis.hwndItem = hwnd;
lpls->dis.hDC = 0;
lpls->dis.itemData = 0;
return TRUE;
}
......
......@@ -408,8 +408,6 @@ BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
LPPOPUPMENU lppop2;
if (lppop == NULL) return;
lpitem = MenuFindItem(lppop, x, y, &wRet);
printf("MenuButtonDown hWnd=%04X x=%d y=%d // wRet=%d lpitem=%08X !\n",
hWnd, x, y, wRet, lpitem);
#ifdef DEBUG_MENU
printf("MenuButtonDown hWnd=%04X x=%d y=%d // wRet=%d lpitem=%08X !\n",
hWnd, x, y, wRet, lpitem);
......@@ -449,6 +447,10 @@ BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
0, lppop->ownerWnd, (LPRECT)NULL);
}
GlobalUnlock(hSubMenu);
return TRUE;
}
if (lppop->BarFlag && !MenuHasFocus) {
MenuFocusLoop(hWnd, lppop);
}
return TRUE;
}
......@@ -506,7 +508,8 @@ void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y)
LPMENUITEM lpitem, lpitem2;
LPPOPUPMENU lppop2;
WORD wRet;
if ((wParam & MK_LBUTTON) != 0) {
/* if ((wParam & MK_LBUTTON) != 0) { */
if (GetKeyState(VK_LBUTTON) != 0) {
lpitem = MenuFindItem(lppop, x, y, &wRet);
#ifdef DEBUG_MENU
printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n",
......@@ -1319,12 +1322,13 @@ BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewIt
GlobalUnlock(hMenu);
return FALSE;
}
lpitem2->hItem = hNewItem;
lpitem2->item_flags = wFlags;
lpitem2->item_id = wItemID;
if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
MF_MENUBREAK | MF_SEPARATOR))) {
/* lpitem2->item_text = GlobalQuickAlloc(strlen(lpNewItem) + 1); */
lpitem2->item_text = GlobalLock(GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1));
lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
lpitem2->item_text = GlobalLock(lpitem2->hText);
if (lpitem2->item_text != NULL)
strcpy(lpitem2->item_text, lpNewItem);
else {
......@@ -1347,8 +1351,6 @@ BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewIt
if (lpitem2->next != NULL) lpitem2->next->prev = lpitem2;
lpitem->next = lpitem2;
}
lpitem2->child = NULL;
lpitem2->parent = NULL;
menu->nItems++;
GlobalUnlock(hMenu);
return TRUE;
......@@ -1386,6 +1388,7 @@ BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
return FALSE;
}
lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
lpitem2->hItem = hNewItem;
if (lpitem2 == NULL) {
GlobalFree(hNewItem);
GlobalUnlock(hMenu);
......@@ -1395,8 +1398,8 @@ BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
lpitem2->item_id = wItemID;
if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
MF_MENUBREAK | MF_SEPARATOR))) {
/* lpitem2->item_text = GlobalQuickAlloc(strlen(lpNewItem) + 1); */
lpitem2->item_text = GlobalLock(GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1));
lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
lpitem2->item_text = GlobalLock(lpitem2->hText);
if (lpitem2->item_text != NULL)
strcpy(lpitem2->item_text, lpNewItem);
else {
......@@ -1414,8 +1417,6 @@ BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
lpitem->next = lpitem2;
lpitem2->prev = lpitem;
lpitem2->next = NULL;
lpitem2->child = NULL;
lpitem2->parent = NULL;
lpitem2->hCheckBit = (HBITMAP)NULL;
lpitem2->hUnCheckBit = (HBITMAP)NULL;
menu->nItems++;
......@@ -1447,9 +1448,10 @@ BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags)
if (!(lpitem->item_flags &
(MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
MF_MENUBREAK | MF_SEPARATOR))) {
GlobalFree((HANDLE)lpitem->item_text);
GlobalUnlock(lpitem->hText);
GlobalFree(lpitem->hText);
}
GlobalFree(lpitem);
GlobalFree(lpitem->hItem);
GlobalUnlock(hMenu);
return TRUE;
}
......@@ -1485,11 +1487,12 @@ BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags)
if (!(lpitem->item_flags &
(MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
MF_MENUBREAK | MF_SEPARATOR))) {
GlobalFree((HANDLE)lpitem->item_text);
GlobalUnlock(lpitem->hText);
GlobalFree(lpitem->hText);
}
if (lpitem->prev) lpitem->prev->next = lpitem->next;
if (lpitem->next) lpitem->next->prev = lpitem->prev;
GlobalFree(lpitem);
GlobalFree(lpitem->hItem);
GlobalUnlock(hMenu);
return TRUE;
}
......@@ -1522,9 +1525,10 @@ BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewIt
if (!(lpitem->item_flags &
(MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
MF_MENUBREAK | MF_SEPARATOR))) {
GlobalFree((HANDLE)lpitem->item_text);
/* lpitem->item_text = GlobalQuickAlloc(strlen(lpNewItem) + 1); */
lpitem->item_text = GlobalLock(GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1));
GlobalUnlock(lpitem->hText);
GlobalFree(lpitem->hText);
lpitem->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
lpitem->item_text = GlobalLock(lpitem->hText);
printf("ModifyMenu %08X %08X '%s') !\n",
lpitem->item_text, lpNewItem, lpNewItem);
if (lpitem->item_text != NULL)
......@@ -1689,13 +1693,26 @@ BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu)
HideAllSubPopupMenu(lpmenu);
break;
}
ScreenToClient(hWnd, &msg.pt);
msg.pt.y += lpmenu->rect.bottom;
switch(msg.message) {
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
case WM_LBUTTONDOWN:
case WM_NCLBUTTONDOWN:
SetCapture(hWnd);
MenuButtonDown(hWnd, lpmenu, msg.pt.x, msg.pt.y);
break;
case WM_LBUTTONUP:
case WM_NCLBUTTONUP:
MenuButtonUp(hWnd, lpmenu, msg.pt.x, msg.pt.y);
ReleaseCapture();
break;
case WM_MOUSEMOVE:
case WM_NCMOUSEMOVE:
MenuMouseMove(hWnd, lpmenu, msg.wParam, msg.pt.x, msg.pt.y);
break;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
PopupMenuWndProc(hWnd, msg.message, msg.wParam, msg.lParam);
default:
DispatchMessage(&msg);
......@@ -1967,12 +1984,15 @@ BOOL SetMenu(HWND hWnd, HMENU hMenu)
return FALSE;
}
lpmenu->ownerWnd = hWnd;
printf("SetMenu(%04X, %04X) // %04X\n", hWnd, hMenu, lpmenu->ownerWnd);
ResetHiliteFlags(lpmenu);
if (GetCapture() == hWnd) ReleaseCapture();
GlobalUnlock(hMenu);
return TRUE;
}
/**********************************************************************
* GetSubMenu [USER.159]
*/
......
This diff is collapsed.
#include "../Wine.tmpl"
#define IHavSubDirs
#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' 'CC=$(CC)'
#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' 'CC=$(CC)' 'MAKE=$(MAKE)'
MODULE = debugger
SUBDIRS = readline
DEFINES = -DUSE_READLINE
/* Quick and dirt hack, since i386 is defined as 1. sigh */
#define temp i386
#undef i386
SRCS = \
dbg.tab.c \
break.c \
hash.c \
lex.yy.c \
info.c \
......@@ -20,6 +23,7 @@ SRCS = \
OBJS = \
dbg.tab.o \
break.o \
hash.o \
lex.yy.o \
info.o \
......
......@@ -9,6 +9,8 @@
*/
#include <stdio.h>
#include <signal.h>
#define YYSTYPE int
#include "regpos.h"
......@@ -24,12 +26,17 @@ void issue_prompt();
%token CONT
%token QUIT
%token HELP
%token BACKTRACE
%token INFO
%token STACK
%token REG
%token REGS
%token NUM
%token ENABLE
%token DISABLE
%token BREAK
%token SET
%token MODE
%token PRINT
%token IDENTIFIER
%token NO_SYMBOL
......@@ -49,12 +56,17 @@ void issue_prompt();
| CONT '\n' { return; };
| SYMBOLFILE IDENTIFIER '\n' { read_symboltable($2); };
| DEFINE IDENTIFIER expr '\n' { add_hash($2, $3); };
| MODE NUM { mode_command($2); };
| ENABLE NUM { enable_break($2); };
| DISABLE NUM { disable_break($2); };
| BREAK '*' expr { add_break($3); };
| x_command
| BACKTRACE '\n' { dbg_bt(); };
| print_command
| deposit_command
deposit_command:
SET REG '=' expr '\n' { regval[$2] = $4; }
SET REG '=' expr '\n' { if(regval) regval[$2] = $4; else application_not_running();}
| SET '*' expr '=' expr '\n' { *((unsigned int *) $3) = $5; }
| SET symbol '=' expr '\n' { *((unsigned int *) $2) = $4; }
......@@ -83,7 +95,7 @@ x_command:
};
expr: NUM { $$ = $1; }
| REG { $$ = regval[$1]; }
| REG { if(regval) $$ = regval[$1]; else application_not_running();}
| symbol { $$ = *((unsigned int *) $1); }
| expr '+' NUM { $$ = $1 + $3; }
| expr '-' NUM { $$ = $1 - $3; };
......@@ -92,6 +104,7 @@ x_command:
infocmd: INFO REGS { info_reg(); }
| INFO STACK { info_stack(); };
| INFO BREAK { info_break(); };
%%
......@@ -103,10 +116,25 @@ issue_prompt(){
#endif
}
void mode_command(int newmode)
{
if(newmode == 16){
dbg_mask = 0xffff;
dbg_mode = 16;
return;
}
if(newmode == 32){
dbg_mask = 0xffffffff;
dbg_mode = 32;
return;
}
fprintf(stderr,"Invalid mode (use 16 or 32)\n");
}
static int loaded_symbols = 0;
void
wine_debug(int * regs)
wine_debug(int signal, int * regs)
{
int i;
#ifdef YYDEBUG
......@@ -143,13 +171,31 @@ wine_debug(int * regs)
};
#endif
/* Remove the breakpoints from memory... */
insert_break(0);
/* If we stopped on a breakpoint, report this fact */
if(signal == SIGTRAP)
{
unsigned int addr;
addr = SC_EIP(dbg_mask);
if((addr & 0xffff0000) == 0 && dbg_mode == 16)
addr |= SC_CS << 16;
fprintf(stderr,"Stopped on breakpoint %d\n", get_bpnum(addr));
}
/* Show where we crashed */
examine_memory(SC_EIP(dbg_mask), 1, 'i');
if(regval)
examine_memory(SC_EIP(dbg_mask), 1, 'i');
issue_prompt();
yyparse();
flush_symbols();
/* Re-insert the breakpoints from memory... */
insert_break(1);
fprintf(stderr,"Returning to Wine...\n");
}
......
......@@ -58,7 +58,7 @@ IDENTIFIER [_a-zA-Z\.~][_a-zA-Z0-9\.~]*
}
{DIGIT}+ {
sscanf(yytext, "%lx", &yylval);
sscanf(yytext, "%ld", &yylval);
return NUM;
}
......@@ -74,14 +74,25 @@ $edx { yylval = RN_EDX; return REG;}
$esi { yylval = RN_ESI; return REG;}
$edi { yylval = RN_EDI; return REG;}
$es { yylval = RN_ES; return REG;}
$ds { yylval = RN_DS; return REG;}
$cs { yylval = RN_CS; return REG;}
$ss { yylval = RN_SS; return REG;}
info|inf|in { return INFO; }
break|brea|bre { return BREAK; }
enable|enabl|enab|ena { return ENABLE;}
disable|disabl|disab|disa|dis { return DISABLE; }
quit|qui|qu { return QUIT; }
help|hel|he { return HELP; }
set|se { return SET; }
bt { return BACKTRACE; }
cont|con|co { return CONT; }
symbolfile|symbolfil|symbolfi|symbolf|symbol|symbo|symb { return SYMBOLFILE; }
......@@ -89,6 +100,8 @@ symbolfile|symbolfil|symbolfi|symbolf|symbol|symbo|symb { return SYMBOLFILE; }
define|defin|defi|def|de { return DEFINE; }
print|prin|pri|pr { return PRINT; }
mode { return MODE; }
regs|reg|re { return REGS; }
stack|stac|sta|st { return STACK; }
......
......@@ -16,6 +16,11 @@ extern int print_insn(char * memaddr, char * realaddr, FILE * stream, int addrle
/* THese three helper functions eliminate the need for patching the
module from gdb for disassembly of code */
void application_not_running()
{
fprintf(stderr,"Application not running\n");
}
void read_memory(char * memaddr, char * buffer, int len){
memcpy(buffer, memaddr, len);
}
......@@ -36,6 +41,12 @@ void print_address(unsigned int addr, FILE * outfile){
void info_reg(){
if(!regval) {
application_not_running();
return 0;
}
fprintf(stderr,"Register dump:\n");
/* First get the segment registers out of the way */
fprintf(stderr," CS:%4.4x SS:%4.4x DS:%4.4x ES:%4.4x GS:%4.4x FS:%4.4x\n",
......@@ -60,6 +71,10 @@ void info_stack(){
unsigned int * dump;
int i;
if(!regval) {
application_not_running();
return 0;
}
fprintf(stderr,"Stack dump:\n");
dump = (int*) SC_EIP(dbg_mask);
......@@ -192,11 +207,15 @@ char * helptext[] = {
"The commands accepted by the Wine debugger are a small subset",
"of the commands that gdb would accept. The commands currently",
"are:\n",
" info reg",
" info stack",
" info [reg,stack,break]",
" break <addr>",
" enable bpnum",
" disable bpnum",
" help",
" quit",
" print <expr>",
" bt",
" mode [16,32]",
" symbolfile <filename>",
" define <identifier> <expr>",
" x <expr>",
......@@ -228,3 +247,52 @@ void dbg_help(){
while(helptext[i]) fprintf(stderr,"%s\n", helptext[i++]);
}
struct frame{
union{
struct {
unsigned short saved_bp;
unsigned short saved_ip;
unsigned short saved_cs;
} win16;
struct {
unsigned long saved_bp;
unsigned long saved_ip;
unsigned short saved_cs;
} win32;
} u;
};
void dbg_bt(){
struct frame * frame;
unsigned short cs;
int frameno = 0;
if(!regval) {
application_not_running();
return 0;
}
fprintf(stderr,"Backtrace:\n");
fprintf(stderr,"%d: %4.4x:%4.4x\n", frameno++, SC_CS, SC_EIP(dbg_mask));
cs = SC_CS;
frame = (struct frame *) ((SC_EBP(dbg_mask) & ~1) | (SC_SS << 16));
while((cs & 3) == 3) {
/* See if in 32 bit mode or not. Assume GDT means 32 bit. */
if ((cs & 7) != 7) {
cs = frame->u.win32.saved_cs;
fprintf(stderr,"%d %4.4x:%4.4x\n", frameno++, cs,
frame->u.win32.saved_ip);
frame = (struct frame *) frame->u.win32.saved_bp;
} else {
cs = frame->u.win16.saved_cs;
fprintf(stderr,"%d %4.4x:%4.4x\n", frameno++, cs,
frame->u.win16.saved_ip);
frame = (struct frame *) ((frame->u.win16.saved_bp & ~1) |
(SC_SS << 16));
}
}
}
......@@ -12,6 +12,7 @@ DLLOBJS = \
dll_gdi.o \
dll_kernel.o \
dll_keyboard.o \
dll_mmsystem.o \
dll_shell.o \
dll_sound.o \
dll_stress.o \
......@@ -35,6 +36,7 @@ MakeDllFromSpec(gdi,$(TOP)/$(MODULE))
MakeDllFromSpec(kernel,$(TOP)/$(MODULE))
MakeDllFromSpec(keyboard,$(TOP)/$(MODULE))
MakeDllFromSpec(shell,$(TOP)/$(MODULE))
MakeDllFromSpec(mmsystem,$(TOP)/$(MODULE))
MakeDllFromSpec(sound,$(TOP)/$(MODULE))
MakeDllFromSpec(stress,$(TOP)/$(MODULE))
MakeDllFromSpec(unixlib,$(TOP)/$(MODULE))
......
......@@ -31,7 +31,7 @@ length 415
25 pascal GlobalCompact(long) GlobalCompact(1)
#26 GLOBALFREEALL
#28 GLOBALMASTERHANDLE
29 pascal Yield() Yield()
29 return Yield 0 0
30 pascal WaitEvent(word) KERNEL_WaitEvent(1)
#31 POSTEVENT
#32 SETPRIORITY
......@@ -119,7 +119,7 @@ length 415
#114 __AHINCR
115 pascal OutputDebugString(ptr) OutputDebugString(1)
#116 INITLIB
117 pascal OldYield() Yield()
117 return OldYield 0 0
#118 GETTASKQUEUEDS
#119 GETTASKQUEUEES
#120 UNDEFDYNLINK
......@@ -147,7 +147,7 @@ length 415
#139 DOSIGNAL
#140 SETSIGHANDLER
#141 INITTASK1
150 pascal DirectedYield() Yield()
150 return DirectedYield 2 0
#151 WINOLDAPCALL
152 pascal GetNumTasks() GetNumTasks()
154 return GlobalNotify 4 0
......
add $8,%esp
popw %es
add $2,%esp
popw %ds
add $2,%esp
popl %edi
popl %esi
popl %ebp
add $4,%esp
popl %ebx
popl %edx
popl %ecx
popl %eax
add $16,%esp
popfl
add $20,%esp
......@@ -24,7 +24,7 @@ static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
#define DEBUG_RELAY /* */
#define N_BUILTINS 10
#define N_BUILTINS 11
struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
{
......@@ -37,7 +37,8 @@ struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
{ "SOUND", SOUND_table, 20, 7 },
{ "KEYBOARD",KEYBOARD_table,137, 8 },
{ "WINSOCK", WINSOCK_table, 155, 9 },
{ "STRESS", STRESS_table, 15,10 },
{ "STRESS", STRESS_table, 15, 10},
{ "MMSYSTEM",MMSYSTEM_table,1023,11},
};
unsigned short *Stack16Frame;
......
......@@ -13,6 +13,7 @@ length 103
2 pascal RegCreateKey() RegCreateKey()
3 pascal RegCloseKey() RegCloseKey()
4 pascal RegDeleteKey() RegDeleteKey()
9 pascal DragAcceptFiles() DragAcceptFiles()
20 pascal ShellExecute(ptr) ShellExecute(1)
102 pascal RegisterShellHook(ptr) RegisterShellHook(1)
103 pascal ShellHookProc() ShellHookProc()
......@@ -21,7 +22,6 @@ length 103
# 33 9 0136 ABOUTDLGPROC exported, shared data
# 34 10 021a EXTRACTICON exported, shared data
# 21 4 1154 FINDEXECUTABLE exported, shared data
# 9 6 0052 DRAGACCEPTFILES exported, shared data
#100 4 0550 HERETHARBETYGARS exported, shared data
# 38 5 0000 FINDENVIRONMENTSTRING exported, shared data
# 7 2 14dc REGENUMKEY exported, shared data
......
......@@ -15,3 +15,10 @@ length 20
8 pascal SETVOICESOUND(word long word) SetVoiceSound(1 2 3)
9 pascal STARTSOUND() StartSound()
10 pascal STOPSOUND() StopSound()
11 pascal WAITSOUNDSTATE(word) WaitSoundState(1)
12 pascal SYNCALLVOICES() SyncAllVoices()
13 pascal COUNTVOICENOTES(word) CountVoiceNotes(1)
14 pascal GETTHRESHOLDEVENT() GetThresholdEvent()
15 pascal GETTHRESHOLDSTATUS() GetThresholdStatus()
16 pascal SETVOICETHRESHOLD(word word) SetVoiceThreshold(1 2)
17 pascal DOBEEP() DoBeep()
......@@ -54,7 +54,7 @@ length 540
49 pascal IsWindowVisible(word) IsWindowVisible(1)
50 pascal FindWindow(ptr ptr) FindWindow(1 2)
#51 BEAR51
#52 ANYPOPUP
52 pascal AnyPopup() AnyPopup()
53 pascal DestroyWindow(word) DestroyWindow(1)
54 pascal EnumWindows(ptr long) EnumWindows(1 2)
55 pascal EnumChildWindows(word ptr long) EnumChildWindows(1 2 3)
......@@ -317,7 +317,7 @@ length 540
325 pascal PaintRect(word word word word ptr) PaintRect(1 2 3 4 5)
#326 GETCONTROLBRUSH
#331 ENABLEHARDWAREINPUT
332 pascal UserYield() Yield()
332 return UserYield 0 0
#333 ISUSERIDLE
334 pascal GetQueueStatus(word) GetQueueStatus(1)
335 pascal GetInputState() GetInputState()
......
......@@ -59,6 +59,7 @@ extern struct dll_table_entry_s USER_table[];
extern struct dll_table_entry_s GDI_table[];
extern struct dll_table_entry_s UNIXLIB_table[];
extern struct dll_table_entry_s WIN87EM_table[];
extern struct dll_table_entry_s MMSYSTEM_table[];
extern struct dll_table_entry_s SHELL_table[];
extern struct dll_table_entry_s SOUND_table[];
extern struct dll_table_entry_s KEYBOARD_table[];
......
......@@ -12,14 +12,12 @@ typedef struct tagMENUITEM
{
struct tagMENUITEM *next;
struct tagMENUITEM *prev;
struct tagMENUITEM *child;
struct tagMENUITEM *parent;
HANDLE hItem;
WORD item_flags;
WORD item_id;
WORD sel_key;
char *shortcut;
char *item_text;
char menu_name[10];
HANDLE hText;
RECT rect;
HBITMAP hCheckBit;
HBITMAP hUnCheckBit;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment