Esempio n. 1
0
/**
 * name:	ShowItem
 * class:	CPsTree
 * desc:	displays on of the items in the treeview
 * param:	iPageIndex	- the index of the treeitem in the array.
 *			needWidth	- gives and takes the width, the treeview must have to show all items properly
 * return:	TRUE if item was added successfully, FALSE otherwise
 **/
HTREEITEM CPsTree::ShowItem(const int iPageIndex, LPWORD needWidth)
{
	TVINSERTSTRUCT tvii;
	CPsTreeItem *pti;

	// check parameters
	if (!_hWndTree || 
		!IsIndexValid(iPageIndex) || 
		!(pti = _pItems[iPageIndex]) ||
		!pti->Name() ||
		!pti->Label())
	{
		MsgErr(GetParent(_hWndTree), LPGENT("Due to a parameter error, one of the treeitems can't be added!"));
		return NULL;
	}	
	// item is visible at the moment
	if ((tvii.itemex.hItem = pti->Hti()) == NULL)
	{
		RECT rc;
		const int iParent = pti->Parent();
		
		// init the rest of the treeitem
		tvii.hParent = IsIndexValid(iParent) ? ShowItem(iParent, needWidth) : NULL;
		tvii.hInsertAfter		= (_dwFlags & PSTVF_SORTTREE) ? TVI_SORT : TVI_LAST;
		tvii.itemex.mask		= TVIF_TEXT|TVIF_PARAM|TVIF_STATE;
		tvii.itemex.pszText		= pti->Label();
		tvii.itemex.state		= pti->State() == DBTVIS_EXPANDED ? TVIS_EXPANDED : 0;
		tvii.itemex.stateMask	= TVIS_EXPANDED;
		tvii.itemex.lParam		= iPageIndex;
		// set images
		if ((tvii.itemex.iImage = tvii.itemex.iSelectedImage = pti->Image()) != -1)
		{
			tvii.itemex.mask |= TVIF_IMAGE|TVIF_SELECTEDIMAGE;
		}
		// insert item into tree if set visible
		if ((tvii.itemex.hItem = TreeView_InsertItem(_hWndTree, &tvii)) == NULL) 
		{
			MsgErr(GetParent(_hWndTree), LPGENT("A fatal error occurred on adding a property sheet page!\nDialog creation aborted!"));
			return NULL;
		}
		pti->Hti(tvii.itemex.hItem);
		// calculate width of treeview
		if (needWidth && TreeView_GetItemRect(_hWndTree, pti->Hti(), &rc, TRUE) && rc.right > *needWidth)
		{
			*needWidth = (WORD)rc.right;
		}
	}
	return tvii.itemex.hItem;
}
Esempio n. 2
0
/**
 * name:	ProfileList_AddNewItem
 * desc:	Ask's user for a type and adds new item to the list view
 * param:	pList	- pointer to the listview's data structure
 *			pszList	- database settings string, that identifies this category
 *
 * return:	TRUE or FALSE
 **/
static BOOLEAN ProfileList_AddNewItem(HWND hDlg, LPLISTCTRL pList, const PROFILEENTRY *pEntry)
{
	LPLCITEM pItem;
	LVITEM lvi;
	HANDLE hContact;

	if (PtrIsValid(pList) && (pItem = (LPLCITEM)mir_alloc(sizeof(LCITEM)))) {
		PSGetContact(hDlg, hContact);
		pItem->nType = CTRL_LIST_ITEM;
		pItem->wFlags = hContact ? CTRLF_HASCUSTOM : 0;
		pItem->iListItem = 0;
		pItem->pszText[0] = NULL;
		pItem->pszText[1] = NULL;
		// get category list
		pEntry->GetList((WPARAM)&pItem->idstrListCount, (LPARAM)&pItem->idstrList);

		lvi.mask = LVIF_PARAM|LVIF_STATE;
		lvi.stateMask = 0xFFFFFFFF;
		lvi.state = LVIS_FOCUSED|LVIS_SELECTED;
		lvi.iItem = ProfileList_GetInsertIndex(pList->hList, pEntry->szGroup);
		lvi.iSubItem = 0;
		lvi.lParam = (LPARAM)pItem;
		if ((lvi.iItem = ListView_InsertItem(pList->hList, &lvi)) >= 0) {
			ProfileList_BeginLabelEdit(pList, lvi.iItem, 0);
			return TRUE;
		}
		mir_free(pItem);
		MsgErr(hDlg, LPGENT("Sorry, but there is a problem with adding a new item of type \"%s\""), pEntry->szGroup);
	}	
	return FALSE;
}
Esempio n. 3
0
DWORD SetHooks( DWORD m_oAction )
{
    DWORD dErr = m_oAction ? ERROR_NAVYHOOK( 0x00 ) : ERROR_NAVYHOOK( 0x02 );
    int i;

    for ( i = 1; i >= 0; i -- )
    {
        HHOOK *hCur = &gm_hRKs + i;

        if ( m_oAction )
        {
            CHECK_ERROR( *hCur = SetWindowsHookEx( WH_KEYBOARD_LL + i, RKsHookProc, gs_hInst, 0 ) );
        }
        else if ( *hCur )
        {
            CHECK_ERROR( UnhookWindowsHookEx( *hCur ) );

            *hCur = 0;
        }
    }

    dErr = ERROR_SUCCESS;

CatchError:

    return MsgErr( dErr, MB_ICONWARNING );
}
Esempio n. 4
0
BOOL SaveIS_FRAME( IS_FRAME *f, COAL *path )
{
    DWORD dErr = ERROR_FRAMSERV( 0x20 );

    int i;
    DWORD dWrt;
    HANDLE hFil;

    BITMAPFILEHEADER bmfh = { MAKEWORD( 'B', 'M' ), S_BFH + S_BIH + f->bih.biSizeImage, 0, 0, S_BFH + S_BIH };

    CHECK_ERROR( ( hFil = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0 ) ) != INVALID_HANDLE_VALUE );

    CHECK_ERROR( WriteFile( hFil, &bmfh, S_BFH, &dWrt, 0 ) && ( dWrt == S_BFH ) );
    CHECK_ERROR( WriteFile( hFil, &f->bih, S_BIH, &dWrt, 0 ) && ( dWrt == S_BIH ) );

    for ( i = f->_y - 1; i >= 0; i -- )
    {
        CHECK_ERROR( WriteFile( hFil, f->dPx + f->_x * i, f->_x << 2, &dWrt, 0 ) && ( dWrt == f->_x << 2 ) );
    }

    dErr = ERROR_SUCCESS;

CatchError:

    if ( hFil ) CloseHandle( hFil );

    return MsgErr( dErr, MB_ICONINFORMATION );
}
Esempio n. 5
0
/**
 * name:	SvcExImINI_Export
 * desc:	Exports a certain contact or all contacts to an ini file.
 * param:	hContact	- contact to export or -1 to export all contacts
 *			pszFileName	- ini-filename to write the contact to
 **/
int SvcExImINI_Export(lpExImParam ExImContact, LPCSTR pszFileName)
{
	FILE* file;
	errno_t err;
	DB::CEnumList Modules;
	SYSTEMTIME now;
	MCONTACT hContact;

	if (!DlgExImModules_SelectModulesToExport(ExImContact, &Modules, NULL))
	{
		if ((err = fopen_s(&file, pszFileName, "wt")) != NULL)
		{
			MsgErr(NULL, 
				LPGENT("The ini-file \"%s\"\nfor saving contact information could not be opened."),
				pszFileName);
			return 1;
		}
		
		SetCursor(LoadCursor(NULL, IDC_WAIT));

		// write header
		GetLocalTime(&now);
		fprintf(file, 
			";DATE = %04d-%02d-%02d %02d:%02d:%02d\n\n",
			now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond
		);

		if (Modules.getCount() == 0)
		{
			Modules.EnumModules();
		}
		
		//	hContact == -1 export entire db.
		if (ExImContact->Typ != EXIM_CONTACT)
		{
			// Owner
			ExportContact(NULL, &Modules, file);
			fprintf(file, "\n\n");
			// Contacts
			for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact))
			{
				ExportContact(hContact, &Modules, file);
				fprintf(file, "\n\n");
			}
		}
		// export only one contact
		else 
		{
			ExportContact(ExImContact->hContact, &Modules, file);
		}

		if (file)
			fclose(file);
		SetCursor(LoadCursor(NULL, IDC_ARROW));
	}
	return 0;
}
Esempio n. 6
0
/**
 * This function checks the version of an iconpack.
 * If the icon pack's version differs from the desired one, 
 * dialog with a warning is displayed.
 *
 * @param		szIconPack	- This is the path to the icon pack. 
 *							  It can be absolute or relative.
 *
 * @return	nothing
 **/
static void IcoLib_CheckIconPackVersion(LPTSTR szIconPack)
{
	if (db_get_b(NULL, MODNAME, SET_ICONS_CHECKFILEVERSION, TRUE)) {
		if (szIconPack) {
			TCHAR szAbsolutePath[MAX_PATH];
			PathToAbsoluteT(szIconPack, szAbsolutePath);

			HMODULE hIconDll = LoadLibrary(szAbsolutePath);
			if (hIconDll) {
				CHAR szFileVersion[64];

				if (!LoadStringA(hIconDll, IDS_ICOPACKVERSION, szFileVersion, sizeof(szFileVersion))
					|| mir_strcmp(szFileVersion, "__UserInfoEx_IconPack_1.2__"))
					MsgErr(NULL, LPGENT("Warning: Your current IconPack's version differs from the one UserInfoEx is designed for.\nSome icons may not be displayed correctly"));
				FreeLibrary(hIconDll);
			}
		}
		else
			MsgErr(NULL, LPGENT("Warning: No IconPack found in one of the following directories: 'customize\\icons', 'icons' or 'plugins'!"));
	}
}
/**
 * name:		DlgExIm_OpenFileName
 * desc:		displayes a slightly modified OpenFileName DialogBox
 * params:		hWndParent		- parent window
 *				pszTitle		- title for the dialog
 *				pszFilter		- the filters to offer
 *				pszFile			- this is the buffer to store the file to (size must be MAX_PATH)
 * return:		-1 on error/abort or filter index otherwise
 **/
int DlgExIm_OpenFileName(HWND hWndParent, LPCSTR pszTitle, LPCSTR pszFilter, LPSTR pszFile)
{
	OPENFILENAMEA ofn;
	CHAR szInitialDir[MAX_PATH];

	InitOpenFileNameStruct(&ofn, hWndParent, pszTitle, pszFilter, szInitialDir, pszFile);
	ofn.Flags |= OFN_PATHMUSTEXIST;
	if (!GetOpenFileNameA(&ofn)) {
		DWORD dwError = CommDlgExtendedError();
		if (dwError) MsgErr(ofn.hwndOwner, LPGENT("The OpenFileDialog returned an error: %d!"), dwError);
		return -1;
	}
	SaveInitialDir(pszFile);
	return ofn.nFilterIndex;
}
Esempio n. 8
0
//---------------------------------------------------------------------------
void CSend::Exit(unsigned int Result)
{
	if (!m_bSilent) {
		bool err = true;
		switch (Result) {
		case CSEND_DIALOG:
			SkinPlaySound("FileDone");
			DialogBoxParam(g_hSendSS, MAKEINTRESOURCE(IDD_UResultForm), 0, ResultDialogProc, (LPARAM)this);
			err = false;
			break;
		case ACKRESULT_SUCCESS:
		case GC_RESULT_SUCCESS:
			SkinPlaySound("FileDone");
			err = false;
			break;
		case ACKRESULT_DENIED:
			SkinPlaySound("FileDenied");
			Error(_T("%s (%i):\nFile transfer denied."), TranslateTS(m_pszSendTyp), Result);
			MsgBoxService(NULL, (LPARAM)&m_box);
			err = false;
			break;
		case GC_RESULT_WRONGVER:	//.You appear to be using the wrong version of GC API.
			Error(_T("%s (%i):\nYou appear to be using the wrong version of GC API"), TranslateT("GCHAT error"), Result);
			break;
		case GC_RESULT_ERROR:		// An internal GC error occurred.
			Error(_T("%s (%i):\nAn internal GC error occurred."), TranslateT("GCHAT error"), Result);
			break;
		case GC_RESULT_NOSESSION:	// contact has no open GC session
			Error(_T("%s (%i):\nContact has no open GC session."), TranslateT("GCHAT error"), Result);
			break;
		case ACKRESULT_FAILED:
		default:
			break;
		}
		if (err) {
			SkinPlaySound("FileFailed");
			if (m_ErrorMsg) MsgBoxService(NULL, (LPARAM)&m_box);
			else MsgErr(NULL, LPGENT("An unknown error has occurred."));
		}
	}
	if (m_pszFile && *m_pszFile && m_bDeleteAfterSend && m_EnableItem&SS_DLG_DELETEAFTERSSEND) {
		DeleteFile(m_pszFile), m_pszFile = NULL;
	}
	if (m_bAsync)
		delete this;/// deletes derived class since destructor is virtual (which also auto-calls base dtor)
}
Esempio n. 9
0
IS_FRAME *MakeIS_FRAME( int f_iX, int f_iY )
{
    DWORD dErr = ERROR_FRAMSERV( 0x00 );
    IS_FRAME *f = 0;

    CHECK_ERROR( ( f_iX > 0 ) && ( f_iY > 0 ) );

    CHECK_ERROR( f = (IS_FRAME *) MemAlloc( sizeof( IS_FRAME ) / 4 ) );
    MemZero( sizeof( IS_FRAME ) / 4, f );

    f->bih.biSize = sizeof( BITMAPINFOHEADER );
    f->bih.biPlanes = 1;
    f->bih.biBitCount = 32;
    f->bih.biSizeImage = f_iX * f_iY << 2;

    f->_x =   ( f->_rl = f_iX );
    f->_y = - ( f->_rt = f_iY );

    CHECK_ERROR( f->hBM = CreateDIBSection( 0, (BITMAPINFO *) &f->bih, 0, &f->dPx, 0, 0 ) );
    f->_y = f_iY;

    CHECK_ERROR( f->hDC = CreateCompatibleDC( 0 ) );
    CHECK_ERROR( f->hGO = SelectObject( f->hDC, f->hBM ) );

    dErr = ERROR_SUCCESS;

CatchError:

    if ( dErr )
    {
        KillIS_FRAME( f );
        f = 0;

        MsgErr( dErr, MB_ICONWARNING );
    }

    return f;
}
Esempio n. 10
0
/**
 * Dialog procedure for the anniversary add/edit dialog
 *
 * @param	 hDlg	- handle to the dialog window
 * @param	 uMsg	- the message to handle
 * @param	 wParam	- parameter
 * @param	 lParam	- parameter
 *
 * @return	different values
 **/
static INT_PTR CALLBACK DlgProc_AnniversaryEditor(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	MAnnivDate *pDlgEditAnniv = (MAnnivDate *)GetUserData(hDlg);

	switch (uMsg) {
	case WM_INITDIALOG:
		pDlgEditAnniv = (MAnnivDate *)lParam;
		if (!PtrIsValid(pDlgEditAnniv))
			break;

		SetUserData(hDlg, lParam);

		// set icons
		if (db_get_b(NULL, MODNAME, SET_ICONS_BUTTONS, 1)) {
			SendDlgItemMessage(hDlg, IDOK, BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_BTN_OK));
			SendDlgItemMessage(hDlg, IDCANCEL, BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_BTN_CANCEL));
		}
		SendDlgItemMessage(hDlg, IDC_HEADERBAR, WM_SETICON, 0, (LPARAM)IcoLib_GetIcon(ICO_DLG_ANNIVERSARY, TRUE));

		// translate controls
		SendDlgItemMessage(hDlg, IDOK, BUTTONTRANSLATE, NULL, NULL);
		SendDlgItemMessage(hDlg, IDCANCEL, BUTTONTRANSLATE, NULL, NULL);
		TranslateDialogDefault(hDlg);

		// init controls
		EnableWindow(GetDlgItem(hDlg, EDIT_CATEGORY), pDlgEditAnniv->Id() != ANID_BIRTHDAY);
		SetDlgItemText(hDlg, EDIT_CATEGORY, pDlgEditAnniv->Description());
		return TRUE;

	case WM_CTLCOLORSTATIC:
		SetBkColor((HDC)wParam, RGB(255, 255, 255));
		return (INT_PTR)GetStockObject(WHITE_BRUSH);

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case EDIT_CATEGORY:
			if (HIWORD(wParam) == EN_UPDATE)
				EnableWindow(GetDlgItem(hDlg, IDOK), GetWindowTextLength((HWND)lParam) > 0);
			break;

		case IDOK: {
			// read new description
			HWND hEdit = GetDlgItem(hDlg, EDIT_CATEGORY);
			int len = Edit_GetTextLength(hEdit);
			LPTSTR pszText;

			if (len == 0
				|| (pszText = (LPTSTR)_alloca((len + 1) * sizeof(TCHAR))) == NULL
				|| !Edit_GetText(hEdit, pszText, len + 1))
			{
				MsgErr(hDlg, LPGENT("Please enter a valid description first!"));
				break;
			}

			if (mir_tstrcmpi(pszText, pDlgEditAnniv->Description())) {
				pDlgEditAnniv->Description(pszText);
				pDlgEditAnniv->SetFlags(MAnnivDate::MADF_HASCUSTOM | MAnnivDate::MADF_CHANGED);
			}
		}
		// fall through
		case IDCANCEL:
			return EndDialog(hDlg, LOWORD(wParam));

		}
	}
	return FALSE;
}
Esempio n. 11
0
INT_PTR CALLBACK PSPProcAnniversary(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	CAnnivEditCtrl *pDateCtrl = CAnnivEditCtrl::GetObj(hDlg, EDIT_ANNIVERSARY_DATE);

	switch (uMsg) {
	case WM_INITDIALOG:
		{
			CCtrlList *pCtrlList = CCtrlList::CreateObj(hDlg);
			if (pCtrlList) {
				HFONT hBoldFont;
				PSGetBoldFont(hDlg, hBoldFont);
				SendDlgItemMessage(hDlg, IDC_PAGETITLE, WM_SETFONT, (WPARAM)hBoldFont, 0);

				TranslateDialogDefault(hDlg);

				pCtrlList->insert(CEditCtrl::CreateObj(hDlg, EDIT_AGE, SET_CONTACT_AGE, DBVT_BYTE));
				pCtrlList->insert(CAnnivEditCtrl::CreateObj(hDlg, EDIT_ANNIVERSARY_DATE, NULL));

				// hContact == NULL or reminder disabled
				CAnnivEditCtrl::GetObj(hDlg, EDIT_ANNIVERSARY_DATE)->EnableReminderCtrl(lParam != NULL);

				SendDlgItemMessage(hDlg, EDIT_AGE, EM_LIMITTEXT, 3, 0);
				SendDlgItemMessage(hDlg, SPIN_AGE, UDM_SETRANGE32, 0, 200);
			}
		}
		break;

	case WM_NOTIFY:
		switch (((LPNMHDR)lParam)->idFrom) {
		case 0:
			switch (((LPNMHDR)lParam)->code) {
			case PSN_ICONCHANGED:
				{
					const ICONCTRL idIcon[] = {
						{ ICO_COMMON_BIRTHDAY, STM_SETIMAGE, ICO_BIRTHDAY },
						{ ICO_BTN_ADD, BM_SETIMAGE, BTN_ADD },
						{ ICO_BTN_DELETE, BM_SETIMAGE, BTN_DELETE }
					};
					IcoLib_SetCtrlIcons(hDlg, idIcon, _countof(idIcon));
				}
				return FALSE;
			}
			break; /* case 0 */

		case EDIT_ANNIVERSARY_DATE:
			if (!PspIsLocked(hDlg) && PtrIsValid(pDateCtrl)) {
				LPNMHDR lpNmhdr = (LPNMHDR)lParam;
				switch (lpNmhdr->code) {
				case DTN_DATETIMECHANGE:
					pDateCtrl->OnDateChanged((LPNMDATETIMECHANGE)lParam);
					break;
				case DTN_DROPDOWN:
					HWND hMonthCal = DateTime_GetMonthCal(lpNmhdr->hwndFrom);
					SetWindowLongPtr(hMonthCal, GWL_STYLE, GetWindowLongPtr(hMonthCal, GWL_STYLE) | MCS_WEEKNUMBERS);
					InvalidateRect(hMonthCal, NULL, TRUE);
				}
			}
			return FALSE;
		}
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case EDIT_REMIND:
			if (!PspIsLocked(hDlg) && HIWORD(wParam) == EN_UPDATE)
			if (PtrIsValid(pDateCtrl))
				pDateCtrl->OnRemindEditChanged();
			return FALSE;

		/**
		* name:	BTN_MENU
		* desc:	the button to dropdown the list to show all items is pressed
		**/
		case BTN_MENU:
			if (HIWORD(wParam) == BN_CLICKED) {
				if (PtrIsValid(pDateCtrl))
					pDateCtrl->OnMenuPopup();
			}
			return FALSE;

		/**
		* name:	BTN_ADD
		* desc:	creates a new dialog to add a new anniversary
		**/
		case BTN_ADD:
			if (HIWORD(wParam) == BN_CLICKED && PtrIsValid(pDateCtrl)) {
				MAnnivDate Date;
				if (IDOK == DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_ANNIVERSARY_EDITOR), hDlg, DlgProc_AnniversaryEditor, (LPARAM)&Date)) {
					SendMessage(GetParent(hDlg), PSM_CHANGED, NULL, NULL);
					if (!pDateCtrl->AddDate(Date))
						pDateCtrl->SetCurSel(pDateCtrl->NumDates() - 1);
				}
			}
			return FALSE;

		/**
		* name:	BTN_EDIT
		* desc:	edit the currently selected anniversary
		**/
		case BTN_EDIT:
			if (HIWORD(wParam) == BN_CLICKED && PtrIsValid(pDateCtrl)) {
				MAnnivDate *pDate = pDateCtrl->Current();
				if (!pDate)
					MsgErr(hDlg, LPGENT("No valid date selected for editing!"));
				else if (
					IDOK == DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_ANNIVERSARY_EDITOR), hDlg, DlgProc_AnniversaryEditor, (LPARAM)pDate) &&
					(pDate->Flags() & (MAnnivDate::MADF_CHANGED | MAnnivDate::MADF_REMINDER_CHANGED)))
				{
					SendMessage(GetParent(hDlg), PSM_CHANGED, NULL, NULL);
					pDateCtrl->SetCurSel(pDateCtrl->CurrentIndex());
				}
			}
			return FALSE;

		/**
		* name:	BTN_DELETE
		* desc:	user wants to delete an anniversary
		**/
		case BTN_DELETE:
			if (HIWORD(wParam) == BN_CLICKED && PtrIsValid(pDateCtrl)) {
				MAnnivDate *pCurrent = pDateCtrl->Current();
				if (pCurrent) {
					int rc = MsgBox(hDlg, MB_YESNO | MB_ICON_QUESTION | MB_NOPOPUP, LPGENT("Delete"), NULL,
						LPGENT("Do you really want to delete the %s?"), pCurrent->Description());

					if (rc == IDYES)
						pDateCtrl->DeleteDate(pDateCtrl->CurrentIndex());
				}
			}
			return FALSE;

		/**
		* name:	CHECK_REMIND
		* desc:	state of reminder checkbox is changed
		**/
		case RADIO_REMIND1:
		case RADIO_REMIND2:
		case RADIO_REMIND3:
			CAnnivEditCtrl *pDateCtrl = CAnnivEditCtrl::GetObj(hDlg, EDIT_ANNIVERSARY_DATE);
			if (PtrIsValid(pDateCtrl) && HIWORD(wParam) == BN_CLICKED)
				pDateCtrl->OnReminderChecked();
			return FALSE;
		} /* switch (LOWORD(wParam)) */
		break;
	}
	return PSPBaseProc(hDlg, uMsg, wParam, lParam);
}
Esempio n. 12
0
/**
 * name:	CtrlContactWndProc
 * desc:	window procedure for the extended combobox class
 * param:	hwnd	- handle to a extended combobox window
 *			msg		- message to handle
 *			wParam	- message specific
 *			lParam	- message specific
 * return:	message specific
 **/
static LRESULT CALLBACK CtrlContactWndProc(HWND hwnd, UINT msg,	WPARAM wParam, LPARAM lParam) 
{
	LPCBEX	cbex = (LPCBEX)GetWindowLongPtr(hwnd, 0);

	switch (msg) {

	/**
	* name:	WM_NCCREATE
	* desc:	is called to initiate the window creation
	* param:	wParam - not used
	*			lParam - pointer to a CREATESTRUCT
	*
	* return:	FALSE on error, TRUE if initialisation was ok
	**/
	case WM_NCCREATE:
	{
		LPCREATESTRUCT cs = (LPCREATESTRUCT)lParam;

		if (!(cbex = (LPCBEX)mir_calloc(1*sizeof(CBEX))))
			return FALSE;
		SetWindowLongPtr(hwnd, 0, (LONG_PTR)cbex);
		cbex->bLocked = 1;
		cbex->hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
		cbex->hInstance = cs->hInstance;
		cbex->iSelectedItem = -1;
		cbex->rect.left = cs->x;
		cbex->rect.top = cs->y;
		cbex->rect.right = cs->x + cs->cx;
		cbex->rect.bottom = cs->y + cs->cy;
		return TRUE;
	}

	/**
		* name:	WM_NCCREATE
		* desc:	is called to create all subitems
		* param:	wParam - not used
		*			lParam - not used
		*
		* return:	FALSE on error, TRUE if initialisation was ok
		**/
	case WM_CREATE:
	{
		WORD wHeight = (WORD)(cbex->rect.bottom - cbex->rect.top);
		WORD wWidth = 130;
		WORD x = 0;

		if (!(cbex->hBtnEdit = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
				UINFOBUTTONCLASS, 
				_T("none"),
				WS_VISIBLE|WS_CHILD|WS_TABSTOP, 0, 0,
				wWidth, wHeight,
				hwnd,
				NULL,
				cbex->hInstance, NULL))) {
			cbex->bLocked = 0;
			return FALSE;
		}
		x += wWidth + 2;
		wWidth = wHeight;
		if (!(cbex->hBtnMenu = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
				UINFOBUTTONCLASS,
				NULL,
				WS_VISIBLE|WS_CHILD|WS_TABSTOP|MBS_PUSHBUTTON|MBS_DOWNARROW,
				x, 0,
				wWidth, wHeight,
				hwnd,
				NULL,
				cbex->hInstance, NULL))) {
			DestroyWindow(cbex->hBtnEdit);
			cbex->bLocked = 0;
			return FALSE;
		}
		x += wWidth + 2;
		wWidth = (WORD)(cbex->rect.right - cbex->rect.left - x - (2 * (wHeight + 2)));
		if (!(cbex->hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,
				_T("Edit"), 
				NULL,
				WS_VISIBLE|WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL,
				x, 1,
				wWidth,	wHeight - 2,
				hwnd,
				NULL,
				cbex->hInstance, NULL))) {
			DestroyWindow(cbex->hBtnEdit);
			DestroyWindow(cbex->hBtnMenu);
			cbex->bLocked = 0;
			return FALSE;
		}
		x += wWidth + 2;
		wWidth = wHeight;
		if (!(cbex->hBtnAdd = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
				UINFOBUTTONCLASS,
				NULL,
				WS_VISIBLE|WS_CHILD|WS_TABSTOP|MBS_FLAT,
				x, 0,
				wWidth, wHeight,
				hwnd,
				NULL,
				cbex->hInstance, NULL))) {
			DestroyWindow(cbex->hBtnEdit);
			DestroyWindow(cbex->hBtnMenu);
			DestroyWindow(cbex->hEdit);
			cbex->bLocked = 0;
			return FALSE;
		}
		x += wWidth + 2;
		if (!(cbex->hBtnDel = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
				UINFOBUTTONCLASS,
				NULL,
				WS_VISIBLE|WS_CHILD|WS_TABSTOP|MBS_FLAT,
				x, 0,
				wWidth, wHeight,
				hwnd,
				NULL,
				cbex->hInstance, NULL))) {
			DestroyWindow(cbex->hBtnEdit);
			DestroyWindow(cbex->hBtnMenu);
			DestroyWindow(cbex->hEdit);
			DestroyWindow(cbex->hBtnAdd);
			cbex->bLocked = 0;
			return FALSE;
		}

		// set ids
		SetWindowLongPtr(cbex->hBtnEdit, GWLP_ID, BTN_EDIT);
		SetWindowLongPtr(cbex->hBtnMenu, GWLP_ID, BTN_MENU);
		SetWindowLongPtr(cbex->hEdit, GWLP_ID, EDIT_VALUE);
		SetWindowLongPtr(cbex->hBtnAdd, GWLP_ID, BTN_ADD);
		SetWindowLongPtr(cbex->hBtnDel, GWLP_ID, BTN_DEL);
		// set fonts & maximum edit control charachters
		SendMessage(cbex->hEdit, WM_SETFONT, (WPARAM)cbex->hFont, NULL);
		SendMessage(cbex->hEdit, EM_LIMITTEXT, (WPARAM)MAXDATASIZE, NULL);
		// add tooltips
		SendMessage(cbex->hBtnMenu, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Choose the item to display"), MBBF_TCHAR);
		SendMessage(cbex->hBtnEdit, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Edit the currently displayed item"), MBBF_TCHAR);
		SendMessage(cbex->hBtnAdd, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Add a new custom item"), MBBF_TCHAR);
		SendMessage(cbex->hBtnDel, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Delete the selected item"), MBBF_TCHAR);
		// reload icons
		CtrlContactWndProc(hwnd, WM_SETICON, NULL, NULL);
		cbex->bLocked = 0;
		return TRUE;
	}

	/**
		* name:	WM_DESTROY
		* desc:	default destroy message, so clear up memory
		* param:	wParam - not used
		*			lParam - not used
		* return:	return value of DefWindowProc
		**/
	case WM_DESTROY:
		CtrlContactWndProc(hwnd, CBEXM_DELALLITEMS, NULL, NULL);
		DestroyWindow(cbex->hBtnEdit);
		DestroyWindow(cbex->hBtnMenu);
		DestroyWindow(cbex->hBtnAdd);
		DestroyWindow(cbex->hBtnDel);
		DestroyWindow(cbex->hEdit);
		MIR_FREE(cbex);
		break;

	/**
		* name:	WM_CTLCOLOREDIT
		* desc:	is called on a paint message for a dialog item to determine its colour scheme
		* param:	wParam - pointer to a HDC
		*			lParam - pointer to a HWND
		* return:	a brush
		**/
	case WM_CTLCOLOREDIT:
		if (!db_get_b(NULL, MODNAME, SET_PROPSHEET_SHOWCOLOURS, 1) || (HWND)lParam != cbex->hEdit || !cbex->pItems || cbex->iSelectedItem < 0) 
			break;
		return Ctrl_SetTextColour((HDC)wParam, cbex->pItems[cbex->iSelectedItem].wFlags);

	case WM_CTLCOLORSTATIC:
		if ((HWND)lParam == cbex->hEdit)
			return (INT_PTR)GetSysColor(COLOR_WINDOW);
		return FALSE;
	/**
		* name:	WM_SETICON
		* desc:	updates the icons of this control
		* param:	wParam - not used
		*			lParam - not used
		* return:	always 0
		**/
	case WM_SETICON:
	{
		HICON hIcon = IcoLib_GetIcon(ICO_BTN_ADD);
		SendMessage(cbex->hBtnAdd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
		SetWindowText(cbex->hBtnAdd, (hIcon ? _T("") : _T("+")));

		hIcon = IcoLib_GetIcon(ICO_BTN_DELETE);
		SendMessage(cbex->hBtnDel, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
		SetWindowText(cbex->hBtnDel, (hIcon ? _T("") : _T("-")));

		if (cbex->pItems && cbex->numItems > 0) {
			for (int i = 0; i < cbex->numItems; i++)
				cbex->pItems[i].hIcon = IcoLib_GetIcon(cbex->pItems[i].pszIcon);

			if (cbex->iSelectedItem >= 0 && cbex->iSelectedItem < cbex->numItems)
				SendMessage(cbex->hBtnEdit, BM_SETIMAGE, IMAGE_ICON, (LPARAM)cbex->pItems[cbex->iSelectedItem].hIcon);
		}
		return 0;
	}

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		/**
		* name:	BTN_MENU
		* desc:	the button to dropdown the list to show all items is pressed
		**/
		case BTN_MENU:
			if (HIWORD(wParam) == BN_CLICKED) {
				POINT pt = { 0, 0 };
				RECT rc;
				int i, nItems;
				HMENU hMenu;

				if (!(hMenu = CreatePopupMenu())) return 0;
				SetFocus((HWND)lParam);

				MENUITEMINFO mii = { 0 };
				mii.cbSize = sizeof(mii);
				mii.fMask = MIIM_ID|MIIM_STRING|MIIM_FTYPE|MIIM_STATE;
				mii.fType = MFT_STRING;

				// insert the items
				for (i = nItems = 0; i < cbex->numItems; i++) {
					if ((cbex->pItems[i].wFlags & CBEXIF_DELETED) || *cbex->pItems[i].szCat == 0) continue;
					mii.fState = (cbex->pItems[i].pszVal && *cbex->pItems[i].pszVal) ? MFS_CHECKED : MFS_UNCHECKED;
					mii.wID = CBEXM_MENIITEMFIRST + i;
					mii.dwTypeData = cbex->pItems[i].szCat;
					if (!InsertMenuItem(hMenu, i, TRUE, &mii)) {
						DestroyMenu(hMenu);
						return 0;
					}
					nItems++;
				}
				// add separator between default and custom items
				if (nItems > 3) {
					mii.fMask = MIIM_FTYPE;
					mii.fType = MFT_SEPARATOR;
					mii.wID = 0;
					mii.dwItemData = 0;
					InsertMenuItem(hMenu, 3, TRUE, &mii);
				}
				ClientToScreen((HWND)lParam, &pt);
				GetClientRect((HWND)lParam, &rc);
				i = TrackPopupMenuEx(hMenu, TPM_RIGHTALIGN|TPM_RETURNCMD, pt.x + rc.right, pt.y + rc.bottom, hwnd, NULL);
				SendMessage(cbex->hBtnMenu, BM_SETCHECK, NULL, NULL);
				if (i >= CBEXM_MENIITEMFIRST && i < CBEXM_MENIITEMFIRST + cbex->numItems) {
					CtrlContactWndProc(hwnd, CBEXM_SETCURSEL, (WPARAM)i - CBEXM_MENIITEMFIRST, NULL);
				}
				DestroyMenu(hMenu);
				return 0;
			}
			break;

		/**
			* name:	BTN_ADD
			* desc:	the button to add a new entry is pressed
			**/
		case BTN_ADD:
			if (HIWORD(wParam) == BN_CLICKED) {
				DLGPROC dlgProc;
				WORD dlgID;
				TCHAR szCat[MAX_CAT] = { 0 };
				TCHAR szVal[MAXDATASIZE] = { 0 };
				CBEXITEM cbi;
				HWND hDlgDetails;

				SetFocus((HWND)lParam);
				if (!(hDlgDetails = GetParent(GetParent(hwnd)))) return 1;
				if (SendMessage(hDlgDetails, PSM_ISLOCKED, NULL, NULL)) return 0;
						
				switch (GetWindowLongPtr(hwnd, GWLP_ID)) {
					case EDIT_PHONE:
						dlgID = IDD_ADDPHONE;
						dlgProc = DlgProc_Phone;
						cbi.pszIcon = ICO_BTN_CUSTOMPHONE;
						break;
					case EDIT_EMAIL:
						dlgID = IDD_ADDEMAIL;
						dlgProc = DlgProc_EMail;
						cbi.pszIcon = ICO_BTN_EMAIL;
						break;
					default:
						return 1;
				}
							
				cbi.iItem = -1;
				cbi.wMask = CBEXIM_CAT|CBEXIM_VAL|CBEXIM_FLAGS|CBEXIM_ICONTEXT;
				cbi.pszCat = szCat;
				cbi.pszVal = szVal;
				cbi.ccCat = MAX_CAT;
				cbi.ccVal = MAXDATASIZE;
				cbi.wFlags = 0;
				cbi.dwID = 0;

				if (DialogBoxParam(ghInst, MAKEINTRESOURCE(dlgID), GetParent(hwnd), dlgProc, (LPARAM)&cbi) == IDOK) {
					MCONTACT hContact = NULL;
							
					SendMessage(hDlgDetails, PSM_GETCONTACT, NULL, (LPARAM)&hContact);
					if (hContact) cbi.wFlags |= CTRLF_HASCUSTOM;
					cbi.wFlags |= CTRLF_CHANGED;
					if (SendMessage(hwnd, CBEXM_ADDITEM, NULL, (LPARAM)&cbi) > CB_ERR) {
						SendMessage(hDlgDetails, PSM_CHANGED, NULL, NULL);
						cbex->bIsChanged = TRUE;
						SendMessage(hwnd, CBEXM_SETCURSEL, cbex->numItems - 1, NULL);
					}
				}
				return 0;
			}
			break;

		/**
			* name:	BTN_EDIT
			* desc:	the button to edit an existing entry is pressed
			**/
		case BTN_EDIT:
			if (HIWORD(wParam) == BN_CLICKED) {
				DLGPROC dlgProc;
				WORD dlgID;
				TCHAR szCat[MAX_CAT] = { 0 };
				TCHAR szVal[MAXDATASIZE] = { 0 };
				CBEXITEM cbi;
				HWND hDlgDetails;

				SetFocus((HWND)lParam);
				if (!(hDlgDetails = GetParent(GetParent(hwnd)))) return 1;
				if (SendMessage(hDlgDetails, PSM_ISLOCKED, NULL, NULL)) return 0;
				if (!cbex->pItems || cbex->iSelectedItem == -1) return 0;

				switch (GetWindowLongPtr(hwnd, GWLP_ID)) {
					case EDIT_PHONE:
						dlgID = IDD_ADDPHONE;
						dlgProc = DlgProc_Phone;
						break;
					case EDIT_EMAIL:
						dlgID = IDD_ADDEMAIL;
						dlgProc = DlgProc_EMail;
						break;
					default:
						return 1;
				}
				cbi.iItem = cbex->iSelectedItem;
				cbi.dwID = 0;
				cbi.wMask = CBEXIM_CAT|CBEXIM_VAL|CBEXIM_FLAGS;
				cbi.pszCat = szCat;
				cbi.pszVal = szVal;
				cbi.ccCat = MAX_CAT;
				cbi.ccVal = MAXDATASIZE;
				if (!CtrlContactWndProc(hwnd, CBEXM_GETITEM, NULL, (LPARAM)&cbi)) {
					MsgErr(hwnd, LPGENT("CRITICAL: Unable to edit current entry!\nThis should not happen!"));
					return 1;
				}

				if (DialogBoxParam(ghInst, MAKEINTRESOURCE(dlgID), GetParent(hwnd), dlgProc, (LPARAM)&cbi) == IDOK) {
					MCONTACT hContact;

					SendMessage(hDlgDetails, PSM_GETCONTACT, NULL, (LPARAM)&hContact);
					if (hContact) cbi.wFlags |= CTRLF_HASCUSTOM;
					cbi.wFlags |= CTRLF_CHANGED;
					SendMessage(hwnd, CBEXM_SETITEM, NULL, (LPARAM)&cbi);
					SendMessage(hDlgDetails, PSM_CHANGED, NULL, NULL);
					cbex->bIsChanged = TRUE;
				}
				return 0;
			}
			break;

		/**
			* name:	BTN_DEL
			* desc:	the button to delete an existing entry is pressed
			**/
		case BTN_DEL:
			if (HIWORD(wParam) == BN_CLICKED) {
				HWND hDlgDetails;
				MSGBOX mBox;
				TCHAR szMsg[MAXDATASIZE];
					
				SetFocus((HWND)lParam);
				if (!(hDlgDetails = GetParent(GetParent(hwnd))) ||
						SendMessage(hDlgDetails, PSM_ISLOCKED, NULL, NULL) ||
						!cbex->pItems ||
						cbex->iSelectedItem < 0 ||
						cbex->iSelectedItem >= cbex->numItems ||
						FAILED(mir_sntprintf(szMsg, TranslateT("Do you really want to delete the current selected item?\n\t%s\n\t%s"),
						cbex->pItems[cbex->iSelectedItem].szCat, cbex->pItems[cbex->iSelectedItem].pszVal))
			)
				{
						return 1;
				}
				mBox.cbSize = sizeof(MSGBOX);
				mBox.hParent = hDlgDetails;
				mBox.hiLogo = IcoLib_GetIcon(ICO_DLG_PHONE);
				mBox.uType = MB_YESNO|MB_ICON_QUESTION|MB_NOPOPUP;
				mBox.ptszTitle = TranslateT("Delete");
				mBox.ptszMsg = szMsg;
				if (IDYES == MsgBoxService(NULL, (LPARAM)&mBox)) {
					// clear value for standard entry
					if (cbex->pItems[cbex->iSelectedItem].wFlags & CBEXIF_CATREADONLY) {
						MIR_FREE(cbex->pItems[cbex->iSelectedItem].pszVal);
						SetWindowText(cbex->hEdit, _T(""));
						cbex->pItems[cbex->iSelectedItem].wFlags &= ~CBEXIF_SMS;
						cbex->pItems[cbex->iSelectedItem].wFlags |= CTRLF_CHANGED;
					}
					// clear values for customized database entry
					else 
					if (cbex->pItems[cbex->iSelectedItem].dwID != 0) {
						MIR_FREE(cbex->pItems[cbex->iSelectedItem].pszVal);
						*cbex->pItems[cbex->iSelectedItem].szCat = 0;
						cbex->pItems[cbex->iSelectedItem].wFlags |= CTRLF_CHANGED|CBEXIF_DELETED;
						CtrlContactWndProc(hwnd, CBEXM_SETCURSEL, cbex->iSelectedItem - 1, FALSE);
					}
					// delete default entry
					else
						CtrlContactWndProc(hwnd, CBEXM_DELITEM, NULL, cbex->iSelectedItem);

					SendMessage(hDlgDetails, PSM_CHANGED, NULL, NULL);
					cbex->bIsChanged = TRUE;
				}
				return 0;
			}
			break;

		/**
			* name:	EDIT_VALUE
			* desc:	the edit control wants us to act
			**/
		case EDIT_VALUE:
			switch (HIWORD(wParam)) {
				case EN_UPDATE:
				{
					TCHAR szVal[MAXDATASIZE] = { 0 };
					int ccVal;
					MCONTACT hContact;
					HWND hDlgDetails = GetParent(GetParent(hwnd));
							
					EnableWindow(cbex->hBtnDel, GetWindowTextLength(cbex->hEdit) > 0);

					if (SendMessage(hDlgDetails, PSM_ISLOCKED, NULL, NULL) ||
						cbex->bLocked || 
						!cbex->pItems || 
						cbex->iSelectedItem < 0 || 
						cbex->iSelectedItem >= cbex->numItems) return 1;

					// get the edit control's text value and check it for syntax
					switch (GetWindowLongPtr(hwnd, GWLP_ID)) {
						case EDIT_PHONE:
						{
							int errorPos;
							TCHAR szEdit[MAXDATASIZE];

							if (ccVal = GetWindowText(cbex->hEdit, szEdit, _countof(szEdit))) {
								if (!(ccVal = CheckPhoneSyntax(szEdit, szVal, MAXDATASIZE, errorPos)) || errorPos > -1) {
									SetWindowText(cbex->hEdit, szVal);
									SendMessage(cbex->hEdit, EM_SETSEL, errorPos, errorPos);
								}
							}
							break;
						}
						case EDIT_EMAIL:
							ccVal = GetWindowText(cbex->hEdit, szVal, _countof(szVal));
							break;
						default:
							ccVal = GetWindowText(cbex->hEdit, szVal, _countof(szVal));
							break;
					}
							
					SendMessage(hDlgDetails, PSM_GETCONTACT, NULL, (LPARAM)&hContact);
					if ((cbex->pItems[cbex->iSelectedItem].wFlags & CTRLF_CHANGED) && !(hContact && (cbex->pItems[cbex->iSelectedItem].wFlags & CTRLF_HASCUSTOM))) return 0;
							
					if (*szVal == 0 || !cbex->pItems[cbex->iSelectedItem].pszVal || mir_tstrcmp(szVal, cbex->pItems[cbex->iSelectedItem].pszVal)) {
						cbex->pItems[cbex->iSelectedItem].wFlags |= CTRLF_CHANGED;
						cbex->pItems[cbex->iSelectedItem].wFlags |= (hContact ? CTRLF_HASCUSTOM : CTRLF_HASPROTO);
						cbex->bIsChanged = TRUE;
						InvalidateRect((HWND)lParam, NULL, TRUE);
						SendMessage(hDlgDetails, PSM_CHANGED, NULL, NULL);
					}
					return 0;
				}
				case EN_KILLFOCUS:
				{
					int ccText;
							
					if (!cbex->pItems || cbex->iSelectedItem < 0 || cbex->iSelectedItem >= cbex->numItems) return 1;
					if (!(cbex->pItems[cbex->iSelectedItem].wFlags & CTRLF_CHANGED)) return 0;

					if ((ccText = GetWindowTextLength(cbex->hEdit)) <= 0) {
						if (cbex->pItems[cbex->iSelectedItem].wFlags & CBEXIF_CATREADONLY) {
							MIR_FREE(cbex->pItems[cbex->iSelectedItem].pszVal);
							SetWindowText(cbex->hEdit, _T(""));
							cbex->pItems[cbex->iSelectedItem].wFlags &= ~CBEXIF_SMS;
						}
						else
							CtrlContactWndProc(hwnd, CBEXM_DELITEM, NULL, cbex->iSelectedItem);
						SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, NULL, NULL);
						cbex->bIsChanged = TRUE;
					}
					else
					if (cbex->pItems[cbex->iSelectedItem].pszVal = (LPTSTR)mir_realloc(cbex->pItems[cbex->iSelectedItem].pszVal, (ccText + 2) * sizeof(TCHAR))) {
						cbex->pItems[cbex->iSelectedItem].pszVal[ccText + 1] = 0;
						GetWindowText(cbex->hEdit, cbex->pItems[cbex->iSelectedItem].pszVal, ccText + 1);
					}
					return 0;
				}
			}
			break;
		}
		break;

	/**
		* name:	CBEXM_ADDITEM
		* desc:	add a item to the control
		* param:	wParam - not used
		*			lParam - (LPCBEXITEM)&item
		* return:	CB_ERR on failure, new item index if successful
		**/
	case CBEXM_ADDITEM:
	{
		LPCBEXITEM	pItem = (LPCBEXITEM)lParam;

		if (!pItem) return FALSE;

		// if an item with the id of pItem exists, change it instead of adding a new one
		// but only if it has not been changed by the user yet.
		if ((pItem->wMask & CBEXIM_ID) && cbex->pItems && pItem->dwID != 0) {
			int iIndex;
				
			for (iIndex = 0; iIndex < cbex->numItems; iIndex++) {
				if (cbex->pItems[iIndex].dwID == pItem->dwID) {
					pItem->iItem = iIndex;
					if (cbex->pItems[iIndex].wFlags & CTRLF_CHANGED)
						pItem->wFlags |= CTRLF_CHANGED;
					else
						CtrlContactWndProc(hwnd, CBEXM_SETITEM, 0, lParam);
					return iIndex;
				}
			}
		}

		// add a new item to the combobox
		if (!(cbex->pItems = (LPCBEXITEMINTERN)mir_realloc(cbex->pItems, (cbex->numItems + 1) * sizeof(CBEXITEMINTERN)))) {
			cbex->numItems = 0;
			return CB_ERR;
		}
		
		// set the ID
		cbex->pItems[cbex->numItems].dwID = (pItem->wMask & CBEXIM_ID) ? pItem->dwID : 0;

		// set category string
		if (!pItem->pszCat || !pItem->pszCat[0] || !mir_tstrncpy(cbex->pItems[cbex->numItems].szCat, pItem->pszCat, MAX_CAT)) {
			mir_sntprintf(cbex->pItems[cbex->numItems].szCat, _T("%s %d"), TranslateT("Other"), ++cbex->numOther);
		}

		// set value string
		if ((pItem->wMask & CBEXIM_VAL) && pItem->pszVal && pItem->pszVal[0])
			cbex->pItems[cbex->numItems].pszVal = mir_tstrdup(pItem->pszVal);
		else
			cbex->pItems[cbex->numItems].pszVal = NULL;
		// set icon
		if ((pItem->wMask & CBEXIM_ICONTEXT) && pItem->pszIcon) {
			cbex->pItems[cbex->numItems].pszIcon = pItem->pszIcon;
			cbex->pItems[cbex->numItems].hIcon = IcoLib_GetIcon(pItem->pszIcon);
		}
		// set flags
		cbex->pItems[cbex->numItems].wFlags = (pItem->wMask & CBEXIM_CAT) ? pItem->wFlags : 0;

		cbex->numItems++;
		return cbex->numItems;
	}

	/**
		* name:	CBEXM_SETITEM
		* desc:	Set an item's information of the control.
		*			If iItem member of CBEXITEM is -1, the currently selected item is changed.
		* param:	wParam - not used
		*			lParam - (LPCBEXITEM)&item
		* return:	CB_ERR on failure, new item index if successful
		**/
	case CBEXM_SETITEM:
	{
		LPCBEXITEM	pItem = (LPCBEXITEM)lParam;

		if (!PtrIsValid(pItem) || !pItem->wMask || !PtrIsValid(cbex->pItems)) return FALSE;
		if (pItem->iItem == -1) pItem->iItem = cbex->iSelectedItem;
		if (pItem->iItem < 0 || pItem->iItem >= cbex->numItems) return FALSE;

		// set new category string
		if (pItem->wMask & CBEXIM_CAT) {
			// set category string
			if (!pItem->pszCat || !pItem->pszCat[0] || !mir_tstrncpy(cbex->pItems[pItem->iItem].szCat, pItem->pszCat, _countof(cbex->pItems[pItem->iItem].szCat))) 
				mir_sntprintf(cbex->pItems[pItem->iItem].szCat, _T("%s %d"), TranslateT("Other"), ++cbex->numOther);
			if (pItem->iItem == cbex->iSelectedItem)
				SetWindowText(cbex->hBtnEdit, cbex->pItems[pItem->iItem].szCat);
		}
		// set new value
		if (pItem->wMask & CBEXIM_VAL) {
			MIR_FREE(cbex->pItems[pItem->iItem].pszVal);
			if (pItem->pszVal && pItem->pszVal[0])
				cbex->pItems[pItem->iItem].pszVal = mir_tstrdup(pItem->pszVal);
			if (pItem->iItem == cbex->iSelectedItem)
				SetWindowText(cbex->hEdit, cbex->pItems[pItem->iItem].pszVal ? cbex->pItems[pItem->iItem].pszVal : _T(""));
		}

		// set icon
		if ((pItem->wMask & CBEXIM_ICONTEXT) && pItem->pszIcon) {
			cbex->pItems[pItem->iItem].pszIcon = pItem->pszIcon;
			cbex->pItems[pItem->iItem].hIcon = IcoLib_GetIcon(pItem->pszIcon);
			if (pItem->iItem == cbex->iSelectedItem)
				SendMessage(cbex->hBtnEdit, BM_SETIMAGE, IMAGE_ICON, (LPARAM)cbex->pItems[pItem->iItem].hIcon);
		}
		if (pItem->wMask & CBEXIM_FLAGS) {
			cbex->pItems[pItem->iItem].wFlags = pItem->wFlags;
			CtrlContactWndProc(hwnd, CBEXM_ENABLEITEM, NULL, NULL);
		}
		return TRUE;
	}

	/**
		* name:	CBEXM_GETITEM
		* desc:	Get an item from the control.
		*			If iItem member of CBEXITEM is -1, the currently selected item is returned.
		* param:	wParam - not used
		*			lParam - (LPCBEXITEM)&item
		* return:	CB_ERR on failure, new item index if successful
		**/
	case CBEXM_GETITEM:
	{
		LPCBEXITEM	pItem = (LPCBEXITEM)lParam;

		if (!pItem || !cbex->pItems) return FALSE;
			
		// try to find item by id
		if ((pItem->wMask & CBEXIM_ID) && pItem->dwID != 0) {
			int i;

			for (i = 0; i < cbex->numItems; i++) {
				if (cbex->pItems[i].dwID == pItem->dwID)
					break;
			}
			pItem->iItem = i;
		}
		else
		if (pItem->iItem == -1) pItem->iItem = cbex->iSelectedItem;
		if (pItem->iItem < 0 || pItem->iItem >= cbex->numItems) return FALSE;
			
		// return only currently selected itemindex
		if (!pItem->wMask) return TRUE;
		// return the unique id
		if (pItem->wMask & CBEXIM_ID) 
			pItem->dwID = cbex->pItems[pItem->iItem].dwID;
		// return category string
		if ((pItem->wMask & CBEXIM_CAT) && pItem->pszCat) {
			if (*cbex->pItems[pItem->iItem].szCat != 0)
				mir_tstrncpy(pItem->pszCat, cbex->pItems[pItem->iItem].szCat, pItem->ccCat - 1);
			else
				*pItem->pszCat = 0;
		}
		// return value string
		if ((pItem->wMask & CBEXIM_VAL) && pItem->pszVal) {
			if (cbex->pItems[pItem->iItem].pszVal)
				mir_tstrncpy(pItem->pszVal, cbex->pItems[pItem->iItem].pszVal, pItem->ccVal - 1);
			else
				*pItem->pszVal = 0;
		}
		// return the icon
		if (pItem->wMask & CBEXIM_ICONTEXT)
			pItem->pszIcon = cbex->pItems[pItem->iItem].pszIcon;
		// return the flags
		if (pItem->wMask & CBEXIM_FLAGS)
			pItem->wFlags = cbex->pItems[pItem->iItem].wFlags;
		return TRUE;
	}

	/**
		* name:	CBEXM_DELITEM
		* desc:	delete an item from the control
		* param:	wParam - not used
		*			lParam - item index
		* return:	CB_ERR on failure, new item index if successful
		**/
	case CBEXM_DELITEM:
	{
		if (!cbex->pItems || (int)lParam < 0 || (int)lParam >= cbex->numItems || (cbex->pItems[lParam].wFlags & CBEXIF_CATREADONLY))
			return FALSE;	
		MIR_FREE(cbex->pItems[(int)lParam].pszVal);
		memmove(cbex->pItems + (int)lParam, 
			cbex->pItems + (int)lParam + 1,
			(cbex->numItems - (int)lParam - 1) * sizeof(CBEXITEMINTERN));
		cbex->numItems--;
		memset((cbex->pItems + cbex->numItems), 0, sizeof(CBEXITEMINTERN));
		CtrlContactWndProc(hwnd, CBEXM_SETCURSEL, lParam - 1, FALSE);
		return TRUE;
	}

	/**
		* name:	CBEXM_DELITEM
		* desc:	delete an item from the control
		* param:	wParam - not used
		*			lParam - item index
		* return:	CB_ERR on failure, new item index if successful
		**/
	case CBEXM_DELALLITEMS:
	{
		int i;

		if (PtrIsValid(cbex)) {
			if (PtrIsValid(cbex->pItems)) {
				for (i = 0; i < cbex->numItems; i++) {
					MIR_FREE(cbex->pItems[i].pszVal);
				}
				MIR_FREE(cbex->pItems);
				cbex->pItems = NULL;
			}
			cbex->numItems = 0;
			cbex->iSelectedItem = -1;
			SetWindowText(cbex->hEdit, _T(""));
			SetWindowText(cbex->hBtnEdit, _T(""));
			SendMessage(cbex->hBtnEdit, WM_SETICON, NULL, NULL);
		}
		return TRUE;
	}

	/**
		* name:	CBEXM_ENABLEITEM
		* desc:	enables or disables the current item
		* param:	wParam - not used
		*			lParam - not used
		* return:	always 0
		**/
	case CBEXM_ENABLEITEM:
		if (cbex->iSelectedItem >= 0 && cbex->iSelectedItem < cbex->numItems) {
			MCONTACT hContact;
			BYTE bEnabled;
				
			PSGetContact(GetParent(hwnd), hContact);

			bEnabled	= !hContact ||
						(cbex->pItems[cbex->iSelectedItem].wFlags & CTRLF_HASCUSTOM) || 
						!(cbex->pItems[cbex->iSelectedItem].wFlags & (CTRLF_HASPROTO|CTRLF_HASMETA)) ||
						!db_get_b(NULL, MODNAME, SET_PROPSHEET_PCBIREADONLY, 0);

			EnableWindow(cbex->hBtnEdit, bEnabled);
			EnableWindow(cbex->hBtnDel, bEnabled && GetWindowTextLength(cbex->hEdit) > 0);
			EnableWindow(cbex->hEdit, bEnabled);
		}
		break;

	/**
		* name:	CBEXM_ISCHANGED
		* desc:	returns whether the control contains changed values or not
		* param:	wParam - not used
		*			lParam - not used
		* return:	TRUE if control was changed, FALSE if nothing was edited
		**/
	case CBEXM_ISCHANGED:
		return cbex->bIsChanged;

	/**
		* name:	CBEXM_RESETCHANGED
		* desc:	resets changed flag to FALSE
		* param:	wParam - not used
		*			lParam - not used
		* return:	always FALSE
		**/
	case CBEXM_RESETCHANGED:
		cbex->bIsChanged = 0;
		return 0;

	/**
		* name:	CBEXM_SETCURSEL
		* desc:	selects a certain item
		* param:	wParam - index of the item to select
		*			lParam - (BYTE)bValid - if TRUE, the next item with a value is selected
		* return:	always FALSE
		**/
	case CBEXM_SETCURSEL:
	{
		int i;

		if (!cbex->pItems) return 1;
		if ((int)wParam < 0 || (int)wParam >= cbex->numItems) wParam = max(cbex->iSelectedItem, 0);
		cbex->bLocked = 1;
			
		if ((BYTE)lParam == TRUE) {
			i = (int)wParam;

			cbex->iSelectedItem = (int)wParam;
			while (i < cbex->numItems) {
				if (cbex->pItems[i].pszVal && *cbex->pItems[i].pszVal) {
					cbex->iSelectedItem = i;
					break;
				}
				i++;
			}
		}
		else {
			// search for the next none deleted item
			for (i = (int)wParam; i < cbex->numItems && *cbex->pItems[i].szCat == 0; i++);
			if (i == cbex->numItems && (int)wParam > 0) {
				for (i = 0; i < (int)wParam && *cbex->pItems[i].szCat == 0; i++);
				cbex->iSelectedItem = i == (int)wParam ? 0 : i;
			}
			else
				cbex->iSelectedItem = i;

		}
		SetWindowText(cbex->hBtnEdit, cbex->pItems[cbex->iSelectedItem].szCat);
		SetWindowText(cbex->hEdit, cbex->pItems[cbex->iSelectedItem].pszVal ? cbex->pItems[cbex->iSelectedItem].pszVal : _T(""));
		SendMessage(cbex->hBtnEdit, BM_SETIMAGE, IMAGE_ICON, (LPARAM)cbex->pItems[cbex->iSelectedItem].hIcon);
		CtrlContactWndProc(hwnd, CBEXM_ENABLEITEM, NULL, NULL);
		cbex->bLocked = 0;
		return 0;
	}
	case CBEXM_SORT:
		if (cbex->numItems > 4) {
			qsort(cbex->pItems + 3, cbex->numItems - 3, sizeof(CBEXITEMINTERN), compareProc);
		}
		return 0;

	case WM_ERASEBKGND:
		return 1;

	case WM_SETFOCUS:
		SetFocus(cbex->hEdit);
		SendMessage(cbex->hEdit, EM_SETSEL, 0, (LPARAM)-1);
		return 0;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}
Esempio n. 13
0
/**
 * name:	 DlgProc_EditPhone()
 * desc:	 dialog procedure
 *
 * return:	 0 or 1
 **/
INT_PTR CALLBACK DlgProc_Phone(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	LPCBEXITEM cbi = (LPCBEXITEM)GetUserData(hDlg);
	static int noRecursion = 0;

	switch (msg) {
	case WM_INITDIALOG:
		{
			UINT i, item, countryCount;
			LPIDSTRLIST	pCountries;
			HWND hCombo = GetDlgItem(hDlg, EDIT_COUNTRY);

			cbi = (LPCBEXITEM)lParam;
			if (!cbi) return FALSE;
			SetUserData(hDlg, lParam);

			SendDlgItemMessage(hDlg, IDC_HEADERBAR, WM_SETICON, 0, (LPARAM)IcoLib_GetIcon(ICO_DLG_PHONE, TRUE));
			if (db_get_b(NULL, MODNAME, SET_ICONS_BUTTONS, 1)) {
				SendDlgItemMessage(hDlg, IDOK, BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_BTN_OK));
				SendDlgItemMessage(hDlg, IDCANCEL, BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_BTN_CANCEL));
			}

			// translate Userinfo buttons
			{
				TCHAR szButton[MAX_PATH];
				HWND hBtn;

				hBtn = GetDlgItem(hDlg, IDOK);
				GetWindowText(hBtn, szButton, _countof(szButton));
				SetWindowText(hBtn, TranslateTS(szButton));
				hBtn = GetDlgItem(hDlg, IDCANCEL);
				GetWindowText(hBtn, szButton, _countof(szButton));
				SetWindowText(hBtn, TranslateTS(szButton));
			}
			if (*cbi->pszVal) SetWindowText(hDlg, LPGENT("Edit phone number"));
			if (cbi->wFlags & CBEXIF_SMS) CheckDlgButton(hDlg, CHECK_SMS, BST_CHECKED);
			TranslateDialogDefault(hDlg);

			EnableWindow(GetDlgItem(hDlg, IDOK), *cbi->pszVal);
			SendDlgItemMessage(hDlg, EDIT_AREA, EM_LIMITTEXT, 31, 0);
			SendDlgItemMessage(hDlg, EDIT_NUMBER, EM_LIMITTEXT, 63, 0);
			SendDlgItemMessage(hDlg, EDIT_CATEGORY, EM_LIMITTEXT, cbi->ccCat - 1, 0);
			SendDlgItemMessage(hDlg, EDIT_PHONE, EM_LIMITTEXT, cbi->ccVal - 1, 0);

			GetCountryList(&countryCount, &pCountries);
			for (i = 0; i < countryCount; i++) {
				if (pCountries[i].nID == 0 || pCountries[i].nID == 0xFFFF) continue;
				item = SendMessage(hCombo, CB_ADDSTRING, NULL, (LPARAM)pCountries[i].ptszTranslated);
				SendMessage(hCombo, CB_SETITEMDATA, item, pCountries[i].nID);
			}

			SetDlgItemText(hDlg, EDIT_PHONE, cbi->pszVal);
			SetDlgItemText(hDlg, EDIT_CATEGORY, cbi->pszCat);
			EnableWindow(GetDlgItem(hDlg, EDIT_CATEGORY), !(cbi->wFlags & CBEXIF_CATREADONLY));
		}
		return TRUE;

	case WM_CTLCOLORSTATIC:
		SetBkColor((HDC)wParam, RGB(255, 255, 255));
		return (INT_PTR)GetStockObject(WHITE_BRUSH);

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
			case IDOK:
				if (HIWORD(wParam) == BN_CLICKED) {
					TCHAR szText[MAXDATASIZE];
					int errorPos;

					if (!GetDlgItemText(hDlg, EDIT_PHONE, szText, _countof(szText)) || !CheckPhoneSyntax(szText, cbi->pszVal, cbi->ccVal, errorPos) || errorPos > -1) {
						MsgErr(hDlg, TranslateT("The phone number should start with a + and consist of\nnumbers, spaces, brackets and hyphens only."));
						break;
					}
					// save category string
					GetDlgItemText(hDlg, EDIT_CATEGORY, cbi->pszCat, cbi->ccCat);

					// save SMS flag
					if ((int)IsDlgButtonChecked(hDlg, CHECK_SMS) != ((cbi->wFlags & CBEXIF_SMS) == CBEXIF_SMS))
						cbi->wFlags ^= CBEXIF_SMS;
				}
				//fall through
			case IDCANCEL:
				if (HIWORD(wParam) == BN_CLICKED) 
					EndDialog(hDlg, wParam);
				break;

		case EDIT_COUNTRY:
			if (HIWORD(wParam) != CBN_SELCHANGE)
				break;

		case EDIT_AREA:
		case EDIT_NUMBER:
			if (LOWORD(wParam) != EDIT_COUNTRY && HIWORD(wParam) != EN_CHANGE) break;
			if (noRecursion) break;
			EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
			{
				TCHAR szPhone[MAXDATASIZE], szArea[32], szData[64];
				int	 nCurSel = SendDlgItemMessage(hDlg, EDIT_COUNTRY, CB_GETCURSEL, 0, 0);
				UINT	nCountry = (nCurSel != CB_ERR) ? SendDlgItemMessage(hDlg, EDIT_COUNTRY, CB_GETITEMDATA, nCurSel, 0) : 0;

				GetDlgItemText(hDlg, EDIT_AREA, szArea, _countof(szArea));
				GetDlgItemText(hDlg, EDIT_NUMBER, szData, _countof(szData));
				mir_sntprintf(szPhone, _T("+%u (%s) %s"), nCountry, szArea, szData);
				noRecursion = 1;
				SetDlgItemText(hDlg, EDIT_PHONE, szPhone);
				noRecursion = 0;
			}
			break;

		case EDIT_PHONE:
			if (HIWORD(wParam) != EN_UPDATE) break;
			if (noRecursion) break;
			noRecursion = 1;
			{
				TCHAR szText[MAXDATASIZE], *pText = 0, *pArea, *pNumber;
				bool isValid = true;
				GetDlgItemText(hDlg, EDIT_PHONE, szText, _countof(szText));
				if (szText[0] != '+')
					isValid = false;
				if (isValid) {
					int country = _tcstol(szText + 1, &pText, 10);
					if (pText - szText > 4)
						isValid = false;
					else {
						int i;
						for (i = SendDlgItemMessage(hDlg, EDIT_COUNTRY, CB_GETCOUNT, 0, 0) - 1; i >= 0; i--) {
							if (country == SendDlgItemMessage(hDlg, EDIT_COUNTRY, CB_GETITEMDATA, i, 0)) {
								SendDlgItemMessage(hDlg, EDIT_COUNTRY, CB_SETCURSEL, i, 0);
								break;
							}
						}
						if (i < 0)
							isValid = false;
					}
				}
				if (isValid) {
					pArea = pText + _tcscspn(pText, _T("0123456789"));
					pText = pArea + _tcsspn(pArea, _T("0123456789"));
					if (*pText) {
						*pText = '\0';
						pNumber = pText + 1 + _tcscspn(pText + 1, _T("0123456789"));
						SetDlgItemText(hDlg, EDIT_NUMBER, pNumber);
					}
					SetDlgItemText(hDlg, EDIT_AREA, pArea);
				}
				if (!isValid) {
					SendDlgItemMessage(hDlg, EDIT_COUNTRY, CB_SETCURSEL, -1, 0);
					SetDlgItemText(hDlg, EDIT_AREA, _T(""));
					SetDlgItemText(hDlg, EDIT_NUMBER, _T(""));
				}
			}
			noRecursion = 0;
			EnableWindow(GetDlgItem(hDlg, IDOK), GetWindowTextLength(GetDlgItem(hDlg, EDIT_PHONE)));
			break;
		}
		break;
	}
	return FALSE;
}
Esempio n. 14
0
/**
 * name:	OnAddPage
 * class:	CPsTreeItem
 * desc:	inits the treeitem's attributes
 * params:	pPsh	- pointer to the property page's header structure
 *			odp		- OPTIONSDIALOGPAGE structure with the information about the page to add
 * return:	0 on success, 1 on failure
 **/
int CPsTreeItem::Create(CPsHdr* pPsh, OPTIONSDIALOGPAGE *odp)
{
	int err;
	TCHAR szTitle[ MAXSETTING ];

	// check parameter
	if (pPsh && pPsh->_dwSize == sizeof(CPsHdr) && odp && PtrIsValid(odp->hInstance)) {
		// instance value
		_hInst = odp->hInstance;
		_dwFlags = odp->flags;
		_initParam = odp->dwInitParam;

		// init page owning contact
		_hContact = pPsh->_hContact;
		_pszProto = mir_strdup(pPsh->_pszProto);

		// global settings prefix for current contact (is dialog owning contact's protocol by default)
		_pszPrefix = (pPsh->_pszPrefix) ? pPsh->_pszPrefix : "Owner";

		if (pPsh->_dwFlags & PSF_PROTOPAGESONLY) {
			if (_dwFlags & ODPF_USERINFOTAB)
				mir_sntprintf(szTitle, _T("%s %d\\%s"), odp->ptszTitle, pPsh->_nSubContact+1, odp->ptszTab);
			else
				mir_sntprintf(szTitle, _T("%s %d"), odp->ptszTitle, pPsh->_nSubContact+1);
		}
		else {
			if (_dwFlags & ODPF_USERINFOTAB)
				mir_sntprintf(szTitle, _T("%s\\%s"), odp->ptszTitle, odp->ptszTab);
			else
				mir_tstrcpy(szTitle, odp->ptszTitle);
		}
		// set the unique utf8 encoded name for the item
		if (err = Name(szTitle, (_dwFlags & ODPF_UNICODE) == ODPF_UNICODE)) 
			MsgErr(NULL, LPGENT("Creating unique name for a page failed with %d and error code %d"), err, GetLastError());

		// read label from database or create it
		else if (err = ItemLabel(TRUE)) 
			MsgErr(NULL, LPGENT("Creating the label for a page failed with %d and error code %d"), err, GetLastError());
		else {
			// load icon for the item
			Icon(pPsh->_hImages, odp, (pPsh->_dwFlags & PSTVF_INITICONS) == PSTVF_INITICONS);
			
			// the rest is not needed if only icons are loaded
			if (pPsh->_dwFlags & PSTVF_INITICONS)
				return 0;

			// load custom order
			if (!(pPsh->_dwFlags & PSTVF_SORTTREE)) {
				_iPosition = (int)db_get_b(NULL, MODNAME, PropertyKey(SET_ITEM_POS), odp->position);
				if ((_iPosition < 0) && (_iPosition > 0x800000A))
					_iPosition = 0;
			}
			// read visibility state
			_bState =	db_get_b(NULL, MODNAME, PropertyKey(SET_ITEM_STATE), DBTVIS_EXPANDED);

			// error for no longer supported dialog template type
			if (((UINT_PTR)odp->pszTemplate & 0xFFFF0000)) 
				MsgErr(NULL, LPGENT("The dialog template type is no longer supported"));
			else {
				// fetch dialog resource id
				_idDlg = (INT_PTR)odp->pszTemplate;
				// dialog procedure
				_pfnDlgProc = odp->pfnDlgProc;

				// is dummy item?
				if (!_idDlg	&& !_pfnDlgProc)
					return 0;

				if (_idDlg	&& _pfnDlgProc) {
					// lock the property pages dialog resource
					_pTemplate = (DLGTEMPLATE*)LockResource(LoadResource(_hInst, FindResource(_hInst, (LPCTSTR)(UINT_PTR)_idDlg, RT_DIALOG)));
					if (_pTemplate)
						return 0;
				}
			}
		}
	}
	return 1;
}
Esempio n. 15
0
/**
 * name:	Import
 * desc:	This function imports an ini file
 * param:	hContact	- handle to contact to match or NULL to match all existing
 *			file		- module to write the setting to
 *			strLine		- string with the setting and its value to write to db
 * return:	0 if writing was ok, 1 otherwise
 **/
int SvcExImINI_Import(MCONTACT hContact, LPCSTR pszFileName)
{
	FILE	*file;
	MCONTACT hNewContact = INVALID_CONTACT_ID;
	DWORD	end,
			numLines				= 0;
	CHAR	szModule[MAXSETTING]	= {0};
	WORD	numContactsInFile		= 0,		// number of contacts in the inifile
			numContactsAdded		= 0;		// number of contacts, that were added to the database
	CHAR	*strBuf					= (CHAR *) mir_alloc(1);
			*strBuf					= 0;
	
	if (file = fopen(pszFileName, "rt")) {
		SetCursor(LoadCursor(NULL, IDC_WAIT));

		while (ImportreadLine(file, strBuf)) {
			numLines++;

			// contact was found and imported
			if (hContact != INVALID_CONTACT_ID && hNewContact != INVALID_CONTACT_ID)
				break;

			// importing settings is only valid vor the main menu item
			if (hContact == INVALID_CONTACT_ID) {
				if (!strncmp(strBuf, "SETTINGS:", 9)) {
					*szModule = 0;
					hNewContact = NULL;
					continue;
				}
			}

			// there are some modules of a contact (import only if contact exist)
			if (!strncmp(strBuf, "FROM CONTACT:", 13)) {
				strBuf = mir_strnerase(strBuf, 0, 13);
				while (strBuf[0] == ' ' || strBuf[0] == '\t')
					strBuf = mir_strnerase(strBuf, 0, 1);

				numContactsInFile++;
				if ((hNewContact = ImportFindContact(hContact, strBuf, FALSE)) != INVALID_CONTACT_ID)
					numContactsAdded++;
				continue;
			}

			// there is a contact to import / add
			if (!strncmp(strBuf, "CONTACT:", 8)) {
				strBuf = mir_strnerase(strBuf, 0, 8);
				while (strBuf[0] == ' ' || strBuf[0] == '\t')
					strBuf = mir_strnerase(strBuf, 0, 1);

				*szModule = 0;
				numContactsInFile++;
				if ((hNewContact = ImportFindContact(hContact, strBuf, TRUE)) != INVALID_CONTACT_ID)
					numContactsAdded++;
				continue;
			}

			// read modules and settings only for valid contacts
			if (hNewContact != INVALID_CONTACT_ID) {
				// found a module line
				if (strBuf[0] == '[' && (end = (strchr(strBuf, ']') - strBuf)) > 0) {
					mir_strncpy(szModule, &strBuf[1], end);
					continue;
				}
				// try to import a setting
				ImportSetting(hNewContact, szModule, strBuf);
			}
		} //end while
		fclose(file);
		mir_free(strBuf);
		SetCursor(LoadCursor(NULL, IDC_ARROW));

		// the contact was not found in the file
		if (numContactsInFile > 0 && !numContactsAdded) {
			MsgErr(NULL,
				LPGENT("None of the %d contacts, stored in the ini-file, match the selected contact!\nNothing will be imported"),
				numContactsInFile);
		}
		// Import complete
		else{
			MsgBox(NULL, MB_ICON_INFO, LPGENT("Import complete"), LPGENT("Some basic statistics"),
				LPGENT("Added %d of %d contacts stored in the ini-file."),
				numContactsAdded, numContactsInFile);
		}
		return 0;
	}
	MsgErr(NULL, 
		LPGENT("The ini-file \"%s\"\nfor reading contact information could not be opened."),
		pszFileName);
	return 1;
}