Example #1
0
int GetDescriptionWidth(const wchar_t *Name=nullptr,const wchar_t *ShortName=nullptr)
{
	int Width=0;
	RenumKeyRecord(FTS.Associations,FTS.TypeFmt,FTS.Type0);

	for (int NumLine=0;; NumLine++)
	{
		string strRegKey;
		strRegKey.Format(FTS.TypeFmt, NumLine);
		string strMask;

		if (!GetRegKey(strRegKey,FTS.Mask, strMask, L""))
			break;

		CFileMask FMask;

		if (!FMask.Set(strMask, FMF_SILENT))
			continue;

		string strDescription;
		GetRegKey(strRegKey,FTS.Desc,strDescription,L"");
		int CurWidth;

		if (!Name)
			CurWidth = HiStrlen(strDescription);
		else
		{
			if (!FMask.Compare(Name))
				continue;

			string strExpandedDesc = strDescription;
			SubstFileName(strExpandedDesc,Name,ShortName,nullptr,nullptr,nullptr,nullptr,TRUE);
			CurWidth = HiStrlen(strExpandedDesc);
		}

		if (CurWidth>Width)
			Width=CurWidth;
	}

	if (Width>ScrX/2)
		Width=ScrX/2;

	return(Width);
}
Example #2
0
size_t GetDescriptionWidth()
{
	size_t Width = 0;
	DWORD Index=0;
	unsigned __int64 id;
	string strMask;
	string strDescription;
	filemasks FMask;

	while (ConfigProvider().AssocConfig()->EnumMasks(Index++,&id,strMask))
	{
		if (!FMask.Set(strMask, FMF_SILENT))
			continue;

		ConfigProvider().AssocConfig()->GetDescription(id,strDescription);
		Width = std::max(Width, HiStrlen(strDescription));
	}

	return Width;
}
Example #3
0
int Message(
    DWORD Flags,
    size_t Buttons,
    const wchar_t *Title,
    const wchar_t * const *Items,
    size_t ItemsNumber,
    Plugin* PluginNumber,
    const GUID* Id
)
{
	string strTempStr;
	string strClipText;
	int X1,Y1,X2,Y2;
	int Length, BtnLength;
	DWORD I, MaxLength, StrCount;
	BOOL ErrorSets=FALSE;
	const wchar_t **Str;
	wchar_t *PtrStr;
	const wchar_t *CPtrStr;
	string strErrStr;

	IsWarningStyle = (Flags&MSG_WARNING) != 0;
	IsErrorType = (Flags&MSG_ERRORTYPE) != 0;

	if(IsErrorType)
	{
		LastError = GetLastError();
		NtStatus = ifn.RtlGetLastNtStatus();
		ErrorSets = GetErrorString(strErrStr);
	}

#if 1 // try to replace inserts
	if (Items && 0 != (Flags & MSG_INSERT_STRINGS))
	{
		string str_err(strErrStr);
		DWORD insert_mask = 0;
		size_t len = strErrStr.GetLength(), pos = 0, inserts_n = 0, inserts[10];

		for (size_t i = 1; i <= ItemsNumber-Buttons; ++i)
		{
			if (0 != (Flags & MSG_INSERT_STR(i)))
			{
				inserts[inserts_n++] = i;
				if (inserts_n >= ARRAYSIZE(inserts))
					break;
			}
		}

		while (str_err.Pos(pos, L"%", pos))
		{
			if (pos >= len-1)
				break;

			if (str_err.At(pos+1) >= L'1' && str_err.At(pos+1) <= L'9')
			{
				size_t insert_i = 0, pos1 = pos+1;
				while (pos1 < len && str_err.At(pos1) >= L'0' && str_err.At(pos1) <= L'9')
				{
					insert_i = 10*insert_i + str_err.At(pos1) - L'0';
					++pos1;
				}
				if (insert_i >= 1 && insert_i <= inserts_n)
				{
					insert_mask |= MSG_INSERT_STR(inserts[insert_i-1]);
					const wchar_t *replacement = Items[inserts[insert_i-1]-1];
					str_err.Replace(pos,pos1-pos,replacement);
					len += wcslen(replacement) - (pos1-pos);
					pos += wcslen(replacement) - (pos1-pos);
				}
				else
					pos = pos1;
			}
			else if (str_err.At(pos+1) == L'%') // "%%"
				pos += 2;
			else
				++pos;
		}
		if (insert_mask == (Flags & MSG_INSERT_STRINGS))
			strErrStr = str_err;
	}
#endif

	// выделим пам¤ть под рабочий массив указателей на строки (+запас 16)
	Str=(const wchar_t **)xf_malloc((ItemsNumber+ADDSPACEFORPSTRFORMESSAGE) * sizeof(wchar_t*));

	if (!Str)
		return -1;

	StrCount=static_cast<DWORD>(ItemsNumber-Buttons);

	// предварительный обсчет максимального размера.
	for (BtnLength=0,I=0; I<static_cast<DWORD>(Buttons); I++) //??
	{
		BtnLength+=HiStrlen(Items[I+StrCount])+2+2+1; // "[ ", " ]", " "
	}
	if(BtnLength)
	{
		BtnLength--;
	}

	DWORD MAX_WIDTH_MESSAGE = Max(ScrX-1-5-5, BtnLength);

	for (MaxLength=BtnLength,I=0; I<StrCount; I++)
	{
		if (static_cast<DWORD>(Length=StrLength(Items[I]))>MaxLength)
			MaxLength=Length;
	}

	// учтем размер заголовка
	if (Title && *Title)
	{
		I=(DWORD)StrLength(Title)+2;

		if (MaxLength < I)
			MaxLength=I;

		strClipText.Append(Title).Append(L"\r\n\r\n");
	}

	// перва¤ коррекци¤ максимального размера
	MaxLength = Min(MaxLength, MAX_WIDTH_MESSAGE);

	// теперь обработаем MSG_ERRORTYPE
	DWORD CountErrorLine=0;

	if ((Flags & MSG_ERRORTYPE) && ErrorSets)
	{
		strClipText.Append(strErrStr).Append(L"\r\n");

		// подсчет количества строк во врапенном сообщениеи
		++CountErrorLine;
		//InsertQuote(ErrStr); // оквочим
		// вычисление "красивого" размера
		DWORD LenErrStr=(DWORD)strErrStr.GetLength();

		if (LenErrStr > MAX_WIDTH_MESSAGE)
		{
			// половина меньше?
			if (LenErrStr/2 < MAX_WIDTH_MESSAGE)
			{
				// а половина + 1/3?
				if ((LenErrStr+LenErrStr/3)/2 < MAX_WIDTH_MESSAGE)
					LenErrStr=(LenErrStr+LenErrStr/3)/2;
				else
					LenErrStr/=2;
			}
			else
				LenErrStr=MAX_WIDTH_MESSAGE;
		}

		MaxLength = Max(MaxLength, LenErrStr);

		// а теперь проврапим
		FarFormatText(strErrStr,LenErrStr,strErrStr,L"\n",0); //?? MaxLength ??
		PtrStr = strErrStr.GetBuffer();

		//BUGBUG: string не предназначен дл¤ хранени¤ строк разделЄнных \0
		while ((PtrStr=wcschr(PtrStr,L'\n')) )
		{
			*PtrStr++=0;

			if (*PtrStr)
				CountErrorLine++;
		}

		strErrStr.ReleaseBuffer();

		if (CountErrorLine > ADDSPACEFORPSTRFORMESSAGE)
			CountErrorLine=ADDSPACEFORPSTRFORMESSAGE; //??
	}

	//BUGBUG: string не предназначен дл¤ хранени¤ строк разделЄнных \0
	// заполн¤ем массив...
	CPtrStr=strErrStr;

	for (I=0; I < CountErrorLine; I++)
	{
		Str[I]=CPtrStr;
		CPtrStr+=StrLength(CPtrStr)+1;

		if (!*CPtrStr) // два идущих подр¤д нул¤ - "хандец" всему
		{
			++I;
			break;
		}
	}

	bool EmptyText=false;
	if(ItemsNumber==Buttons && !I)
	{
		EmptyText=true;
		Str[I]=L"";
		I++;
		StrCount++;
		ItemsNumber++;
	}

	for (size_t J=0; J < ItemsNumber-(EmptyText?1:0); ++J, ++I)
	{
		Str[I]=Items[J];
	}

	for (size_t i = 0; i < ItemsNumber-Buttons; ++i)
	{
		strClipText.Append(Items[i]).Append(L"\r\n");
	}
	strClipText.Append(L"\r\n");
	for (size_t i = ItemsNumber-Buttons; i < ItemsNumber; ++i)
	{
		if(i > ItemsNumber-Buttons)
		{
			strClipText.Append(L' ');
		}
		strClipText.Append(Items[i]);
	}

	StrCount+=CountErrorLine;
	MessageX1=X1=(int(ScrX-MaxLength))/2-4;
	MessageX2=X2=X1+MaxLength+9;
	Y1=(ScrY-static_cast<int>(StrCount))/2-2;

	if (Y1 < 0)
		Y1=0;

	MessageY1=Y1;
	MessageY2=Y2=Y1+StrCount+3;
	string strHelpTopic(strMsgHelpTopic);
	strMsgHelpTopic.Clear();
	// *** ¬ариант с ƒиалогом ***

	if (Buttons>0)
	{
		size_t ItemCount=StrCount+Buttons+1;
		DialogItemEx *PtrMsgDlg;
		DialogItemEx *MsgDlg = new DialogItemEx[ItemCount+1];

		if (!MsgDlg)
		{
			xf_free(Str);
			return -1;
		}

		for (DWORD i=0; i<ItemCount+1; i++)
			MsgDlg[i].Clear();

		int RetCode;
		MessageY2=++Y2;
		MsgDlg[0].Type=DI_DOUBLEBOX;
		MsgDlg[0].X1=3;
		MsgDlg[0].Y1=1;
		MsgDlg[0].X2=X2-X1-3;
		MsgDlg[0].Y2=Y2-Y1-1;

		if (Title && *Title)
			MsgDlg[0].strData = Title;

		FARDIALOGITEMTYPES TypeItem=DI_TEXT;
		unsigned __int64 FlagsItem=DIF_SHOWAMPERSAND;
		BOOL IsButton=FALSE;
		int CurItem=0;
		bool StrSeparator=false;
		bool Separator=false;
		for (PtrMsgDlg=MsgDlg+1,I=1; I < ItemCount; ++I, ++PtrMsgDlg, ++CurItem)
		{
			if (I==StrCount+1 && !StrSeparator && !Separator)
			{
				PtrMsgDlg->Type=DI_TEXT;
				PtrMsgDlg->Flags=DIF_SEPARATOR;
				PtrMsgDlg->Y1=PtrMsgDlg->Y2=I+1;
				CurItem--;
				I--;
				Separator=true;
				continue;
			}
			if(I==StrCount+1)
			{
				TypeItem=DI_BUTTON;
				FlagsItem=DIF_CENTERGROUP|DIF_DEFAULTBUTTON|DIF_FOCUS;
				IsButton=TRUE;
				FirstButtonIndex=CurItem+1;
				LastButtonIndex=CurItem;
			}
			else
			{
				FlagsItem&=~DIF_DEFAULTBUTTON;
			}

			PtrMsgDlg->Type=TypeItem;
			PtrMsgDlg->Flags|=FlagsItem;
			CPtrStr=Str[CurItem];

			if (IsButton)
			{
				PtrMsgDlg->Y1=Y2-Y1-2+(Separator?1:0);
				PtrMsgDlg->strData+=CPtrStr;
				LastButtonIndex++;
			}
			else
			{
				PtrMsgDlg->X1=(Flags & MSG_LEFTALIGN)?5:-1;
				PtrMsgDlg->Y1=I+1;
				wchar_t Chr=*CPtrStr;

				if (Chr == L'\1' || Chr == L'\2')
				{
					CPtrStr++;
					PtrMsgDlg->Flags|=(Chr==2?DIF_SEPARATOR2:DIF_SEPARATOR);
					if(I==StrCount)
					{
						StrSeparator=true;
					}
				}
				else
				{
					if (StrLength(CPtrStr)>X2-X1-9)
					{
						PtrMsgDlg->Type=DI_EDIT;
						PtrMsgDlg->Flags|=DIF_READONLY|DIF_BTNNOCLOSE|DIF_SELECTONENTRY;
						PtrMsgDlg->X1=5;
						PtrMsgDlg->X2=X2-X1-5;
						PtrMsgDlg->strData=CPtrStr;
					}
					else
					{
						//xstrncpy(PtrMsgDlg->Data,CPtrStr,Min((int)MAX_WIDTH_MESSAGE,(int)sizeof(PtrMsgDlg->Data))); //?? ScrX-15 ??
						PtrMsgDlg->strData = CPtrStr; //BUGBUG, wrong len
					}
				}
			}
		}

		{
			if(Separator)
			{
				FirstButtonIndex++;
				LastButtonIndex++;
				MessageY2++;
				Y2++;
				MsgDlg[0].Y2++;
				ItemCount++;
			}
			Dialog Dlg(MsgDlg,ItemCount,MsgDlgProc, &strClipText);
			if (X1 == -1) X1 = 0;
			if (Y1 == -1) Y1 = 0;
			Dlg.SetPosition(X1,Y1,X2,Y2);
			if(Id) Dlg.SetId(*Id);

			if (!strHelpTopic.IsEmpty())
				Dlg.SetHelp(strHelpTopic);

			Dlg.SetPluginOwner(reinterpret_cast<Plugin*>(PluginNumber)); // «апомним номер плагина

			if (IsWarningStyle)
			{
				Dlg.SetDialogMode(DMODE_WARNINGSTYLE);
			}

			Dlg.SetDialogMode(DMODE_MSGINTERNAL);
			if (Flags & MSG_NOPLUGINS)
				Dlg.SetDialogMode(DMODE_NOPLUGINS);
			FlushInputBuffer();

			if (Flags & MSG_KILLSAVESCREEN)
				SendDlgMessage((HANDLE)&Dlg,DM_KILLSAVESCREEN,0,0);

			Dlg.Process();
			RetCode=Dlg.GetExitCode();
		}

		delete [] MsgDlg;
		xf_free(Str);
		return(RetCode<0?RetCode:RetCode-StrCount-1-(Separator?1:0));
	}

	// *** Ѕез ƒиалога! ***
	SetCursorType(0,0);

	if (!(Flags & MSG_KEEPBACKGROUND))
	{
		SetScreen(X1,Y1,X2,Y2,L' ',ColorIndexToColor((Flags & MSG_WARNING)?COL_WARNDIALOGTEXT:COL_DIALOGTEXT));
		MakeShadow(X1+2,Y2+1,X2+2,Y2+1);
		MakeShadow(X2+1,Y1+1,X2+2,Y2+1);
		Box(X1+3,Y1+1,X2-3,Y2-1,ColorIndexToColor((Flags & MSG_WARNING)?COL_WARNDIALOGBOX:COL_DIALOGBOX),DOUBLE_BOX);
	}

	SetColor((Flags & MSG_WARNING)?COL_WARNDIALOGTEXT:COL_DIALOGTEXT);

	if (Title && *Title)
	{
		string strTempTitle = Title;

		if (strTempTitle.GetLength() > MaxLength)
			strTempTitle.SetLength(MaxLength);

		GotoXY(X1+(X2-X1-1-(int)strTempTitle.GetLength())/2,Y1+1);
		FS<<L" "<<strTempTitle<<L" ";
	}

	for (I=0; I<StrCount; I++)
	{
		CPtrStr=Str[I];
		wchar_t Chr=*CPtrStr;

		if (Chr == 1 || Chr == 2)
		{
			Length=X2-X1-5;

			if (Length>1)
			{
				SetColor((Flags & MSG_WARNING)?COL_WARNDIALOGBOX:COL_DIALOGBOX);
				GotoXY(X1+3,Y1+I+2);
				DrawLine(Length,(Chr == 2?3:1));
				CPtrStr++;
				int TextLength=StrLength(CPtrStr);

				if (TextLength<Length)
				{
					GotoXY(X1+3+(Length-TextLength)/2,Y1+I+2);
					Text(CPtrStr);
				}

				SetColor((Flags & MSG_WARNING)?COL_WARNDIALOGBOX:COL_DIALOGTEXT);
			}

			continue;
		}

		if ((Length=StrLength(CPtrStr))>ScrX-15)
			Length=ScrX-15;

		int Width=X2-X1+1;
		wchar_t *lpwszTemp = nullptr;
		int PosX;
		if (Flags & MSG_LEFTALIGN)
		{
			lpwszTemp = (wchar_t*)xf_malloc((Width-10+1)*sizeof(wchar_t));
			_snwprintf(lpwszTemp,Width-10+1,L"%.*s",Width-10,CPtrStr);
			GotoXY(X1+5,Y1+I+2);
		}
		else
		{
			PosX=X1+(Width-Length)/2;
			lpwszTemp = (wchar_t*)xf_malloc((PosX-X1-4+Length+X2-PosX-Length-3+1)*sizeof(wchar_t));
			_snwprintf(lpwszTemp,PosX-X1-4+Length+X2-PosX-Length-3+1,L"%*s%.*s%*s",PosX-X1-4,L"",Length,CPtrStr,X2-PosX-Length-3,L"");
			GotoXY(X1+4,Y1+I+2);
		}

		Text(lpwszTemp);
		xf_free(lpwszTemp);
	}

	/* $ 13.01.2003 IS
	   - ѕринудительно уберем запрет отрисовки экрана, если количество кнопок
	     в сообщении равно нулю и макрос закончил выполн¤тьс¤. Ёто необходимо,
	     чтобы заработал прогресс-бар от плагина, который был запущен при помощи
	     макроса запретом отрисовки (bugz#533).
	*/
	xf_free(Str);

	if (!Buttons)
	{
		if (ScrBuf.GetLockCount()>0 && !CtrlObject->Macro.PeekKey())
			ScrBuf.SetLockCount(0);

		ScrBuf.Flush();
	}

	return 0;
}
Example #4
0
int Message(
    DWORD Flags,
    int Buttons,
    const wchar_t *Title,
    const wchar_t * const *Items,
    int ItemsNumber,
    INT_PTR PluginNumber
)
{
	FARString strTempStr;
	int X1,Y1,X2,Y2;
	int Length, BtnLength, J;
	DWORD I, MaxLength, StrCount;
	BOOL ErrorSets=FALSE;
	const wchar_t **Str;
	wchar_t *PtrStr;
	const wchar_t *CPtrStr;
	FARString strErrStr;

	if (Flags & MSG_ERRORTYPE)
		ErrorSets = GetErrorString(strErrStr);

	// выделим память под рабочий массив указателей на строки (+запас 16)
	Str=(const wchar_t **)xf_malloc((ItemsNumber+ADDSPACEFORPSTRFORMESSAGE) * sizeof(wchar_t*));

	if (!Str)
		return -1;

	StrCount=ItemsNumber-Buttons;

	// предварительный обсчет максимального размера.
	for (BtnLength=0,I=0; I<static_cast<DWORD>(Buttons); I++) //??
	{
		BtnLength+=HiStrlen(Items[I+StrCount])+2+2+1; // "[ ", " ]", " "
	}
	if(BtnLength)
	{
		BtnLength--;
	}

	for (MaxLength=BtnLength,I=0; I<StrCount; I++)
	{
		if (static_cast<DWORD>(Length=StrLength(Items[I]))>MaxLength)
			MaxLength=Length;
	}

	// учтем так же размер заголовка
	if (Title && *Title)
	{
		I=(DWORD)StrLength(Title)+2;

		if (MaxLength < I)
			MaxLength=I;
	}

	// певая коррекция максимального размера
	if (MaxLength > MAX_WIDTH_MESSAGE)
		MaxLength=MAX_WIDTH_MESSAGE;

	// теперь обработаем MSG_ERRORTYPE
	DWORD CountErrorLine=0;

	if ((Flags & MSG_ERRORTYPE) && ErrorSets)
	{
		// подсчет количества строк во врапенном сообщениеи
		++CountErrorLine;
		//InsertQuote(ErrStr); // оквочим
		// вычисление "красивого" размера
		DWORD LenErrStr=(DWORD)strErrStr.GetLength();

		if (LenErrStr > MAX_WIDTH_MESSAGE)
		{
			// половина меньше?
			if (LenErrStr/2 < MAX_WIDTH_MESSAGE)
			{
				// а половина + 1/3?
				if ((LenErrStr+LenErrStr/3)/2 < MAX_WIDTH_MESSAGE)
					LenErrStr=(LenErrStr+LenErrStr/3)/2;
				else
					LenErrStr/=2;
			}
			else
				LenErrStr=MAX_WIDTH_MESSAGE;
		}
		else if (LenErrStr < MaxLength)
			LenErrStr=MaxLength;

		if (MaxLength > LenErrStr && MaxLength >= MAX_WIDTH_MESSAGE)
			MaxLength=LenErrStr;

		if (MaxLength < LenErrStr && LenErrStr <= MAX_WIDTH_MESSAGE)
			MaxLength=LenErrStr;

		// а теперь проврапим
		//PtrStr=FarFormatText(ErrStr,MaxLength-(MaxLength > MAX_WIDTH_MESSAGE/2?1:0),ErrStr,sizeof(ErrStr),"\n",0); //?? MaxLength ??
		FarFormatText(strErrStr,LenErrStr,strErrStr,L"\n",0); //?? MaxLength ??
		PtrStr = strErrStr.GetBuffer();

		//BUGBUG: FARString не преднозначен для хранения строк разделённых \0
		while ((PtrStr=wcschr(PtrStr,L'\n')) )
		{
			*PtrStr++=0;

			if (*PtrStr)
				CountErrorLine++;
		}

		strErrStr.ReleaseBuffer();

		if (CountErrorLine > ADDSPACEFORPSTRFORMESSAGE)
			CountErrorLine=ADDSPACEFORPSTRFORMESSAGE; //??
	}

	//BUGBUG: FARString не преднозначен для хранения строк разделённых \0
	// заполняем массив...
	CPtrStr=strErrStr;

	for (I=0; I < CountErrorLine; I++)
	{
		Str[I]=CPtrStr;
		CPtrStr+=StrLength(CPtrStr)+1;

		if (!*CPtrStr) // два идущих подряд нуля - "хандец" всему
		{
			++I;
			break;
		}
	}

	bool EmptyText=false;
	if(ItemsNumber==Buttons && !I)
	{
		EmptyText=true;
		Str[I]=L"";
		I++;
		StrCount++;
		ItemsNumber++;
	}

	for (J=0; J < ItemsNumber-(EmptyText?1:0); ++J, ++I)
	{
		Str[I]=Items[J];
	}

	StrCount+=CountErrorLine;
	MessageX1=X1=(ScrX-MaxLength)/2-4;
	MessageX2=X2=X1+MaxLength+9;
	Y1=(ScrY-StrCount)/2-2;

	if (Y1 < 0)
		Y1=0;

	MessageY1=Y1;
	MessageY2=Y2=Y1+StrCount+3;
	FARString strHelpTopic(strMsgHelpTopic);
	strMsgHelpTopic.Clear();
	// *** Вариант с Диалогом ***

	if (Buttons>0)
	{
		DWORD ItemCount=StrCount+Buttons+1;
		DialogItemEx *PtrMsgDlg;
		DialogItemEx *MsgDlg = new(std::nothrow) DialogItemEx[ItemCount+1];

		if (!MsgDlg)
		{
			xf_free(Str);
			return -1;
		}

		for (DWORD i=0; i<ItemCount+1; i++)
			MsgDlg[i].Clear();

		int RetCode;
		MessageY2=++Y2;
		MsgDlg[0].Type=DI_DOUBLEBOX;
		MsgDlg[0].X1=3;
		MsgDlg[0].Y1=1;
		MsgDlg[0].X2=X2-X1-3;
		MsgDlg[0].Y2=Y2-Y1-1;

		if (Title && *Title)
			MsgDlg[0].strData = Title;

		int TypeItem=DI_TEXT;
		DWORD FlagsItem=DIF_SHOWAMPERSAND;
		BOOL IsButton=FALSE;
		int CurItem=0;
		bool StrSeparator=false;
		bool Separator=false;
		for (PtrMsgDlg=MsgDlg+1,I=1; I < ItemCount; ++I, ++PtrMsgDlg, ++CurItem)
		{
			if (I==StrCount+1 && !StrSeparator && !Separator)
			{
				PtrMsgDlg->Type=DI_TEXT;
				PtrMsgDlg->Flags=DIF_SEPARATOR;
				PtrMsgDlg->Y1=PtrMsgDlg->Y2=I+1;
				CurItem--;
				I--;
				Separator=true;
				continue;
			}
			if(I==StrCount+1)
			{
				PtrMsgDlg->DefaultButton=TRUE;
				PtrMsgDlg->Focus=TRUE;
				TypeItem=DI_BUTTON;
				FlagsItem=DIF_CENTERGROUP;
				IsButton=TRUE;
				FirstButtonIndex=CurItem+1;
				LastButtonIndex=CurItem;
			}

			PtrMsgDlg->Type=TypeItem;
			PtrMsgDlg->Flags|=FlagsItem;
			CPtrStr=Str[CurItem];

			if (IsButton)
			{
				PtrMsgDlg->Y1=Y2-Y1-2+(Separator?1:0);
				PtrMsgDlg->strData+=CPtrStr;
				LastButtonIndex++;
			}
			else
			{
				PtrMsgDlg->X1=(Flags & MSG_LEFTALIGN)?5:-1;
				PtrMsgDlg->Y1=I+1;
				wchar_t Chr=*CPtrStr;

				if (Chr == L'\1' || Chr == L'\2')
				{
					CPtrStr++;
					PtrMsgDlg->Flags|=(Chr==2?DIF_SEPARATOR2:DIF_SEPARATOR);
					if(I==StrCount)
					{
						StrSeparator=true;
					}
				}
				else if (StrLength(CPtrStr)>X2-X1-9)
				{
					PtrMsgDlg->Type=DI_EDIT;
					PtrMsgDlg->Flags|=DIF_READONLY|DIF_BTNNOCLOSE|DIF_SELECTONENTRY;
					PtrMsgDlg->X1=5;
					PtrMsgDlg->X2=X2-X1-5;
					PtrMsgDlg->strData=CPtrStr;
					continue;
				}

				//xstrncpy(PtrMsgDlg->Data,CPtrStr,Min((int)MAX_WIDTH_MESSAGE,(int)sizeof(PtrMsgDlg->Data))); //?? ScrX-15 ??
				PtrMsgDlg->strData = CPtrStr; //BUGBUG, wrong len
			}
		}

		{
			if(Separator)
			{
				FirstButtonIndex++;
				LastButtonIndex++;
				MessageY2++;
				Y2++;
				MsgDlg[0].Y2++;
				ItemCount++;
			}
			IsWarningStyle=Flags&MSG_WARNING;
			Dialog Dlg(MsgDlg,ItemCount,MsgDlgProc);
			Dlg.SetPosition(X1,Y1,X2,Y2);

			if (!strHelpTopic.IsEmpty())
				Dlg.SetHelp(strHelpTopic);

			Dlg.SetPluginNumber(PluginNumber); // Запомним номер плагина

			if (IsWarningStyle)
			{
				Dlg.SetDialogMode(DMODE_WARNINGSTYLE);
			}

			Dlg.SetDialogMode(DMODE_MSGINTERNAL);
			FlushInputBuffer();

			if (Flags & MSG_KILLSAVESCREEN)
				SendDlgMessage((HANDLE)&Dlg,DM_KILLSAVESCREEN,0,0);

			Dlg.Process();
			RetCode=Dlg.GetExitCode();
		}

		delete [] MsgDlg;
		xf_free(Str);
		return(RetCode<0?RetCode:RetCode-StrCount-1-(Separator?1:0));
	}

	// *** Без Диалога! ***
	SetCursorType(0,0);

	if (!(Flags & MSG_KEEPBACKGROUND))
	{
		SetScreen(X1,Y1,X2,Y2,L' ',(Flags & MSG_WARNING)?COL_WARNDIALOGTEXT:COL_DIALOGTEXT);
		MakeShadow(X1+2,Y2+1,X2+2,Y2+1);
		MakeShadow(X2+1,Y1+1,X2+2,Y2+1);
		Box(X1+3,Y1+1,X2-3,Y2-1,(Flags & MSG_WARNING)?COL_WARNDIALOGBOX:COL_DIALOGBOX,DOUBLE_BOX);
	}

	SetColor((Flags & MSG_WARNING)?COL_WARNDIALOGTEXT:COL_DIALOGTEXT);

	if (Title && *Title)
	{
		FARString strTempTitle = Title;

		if (strTempTitle.GetLength() > MaxLength)
			strTempTitle.SetLength(MaxLength);

		GotoXY(X1+(X2-X1-1-(int)strTempTitle.GetLength())/2,Y1+1);
		FS<<L" "<<strTempTitle<<L" ";
	}

	for (I=0; I<StrCount; I++)
	{
		int PosX;
		CPtrStr=Str[I];
		wchar_t Chr=*CPtrStr;

		if (Chr == 1 || Chr == 2)
		{
			int Length=X2-X1-5;

			if (Length>1)
			{
				SetColor((Flags & MSG_WARNING)?COL_WARNDIALOGBOX:COL_DIALOGBOX);
				GotoXY(X1+3,Y1+I+2);
				DrawLine(Length,(Chr == 2?3:1));
				CPtrStr++;
				int TextLength=StrLength(CPtrStr);

				if (TextLength<Length)
				{
					GotoXY(X1+3+(Length-TextLength)/2,Y1+I+2);
					Text(CPtrStr);
				}

				SetColor((Flags & MSG_WARNING)?COL_WARNDIALOGBOX:COL_DIALOGTEXT);
			}

			continue;
		}

		if ((Length=StrLength(CPtrStr))>ScrX-15)
			Length=ScrX-15;

		int Width=X2-X1+1;
		wchar_t *lpwszTemp = nullptr;

		if (Flags & MSG_LEFTALIGN)
		{
			lpwszTemp = (wchar_t*)xf_malloc((Width-10+1)*sizeof(wchar_t));
			swprintf(lpwszTemp,Width-10+1,L"%.*ls",Width-10,CPtrStr);
			GotoXY(X1+5,Y1+I+2);
		}
		else
		{
			PosX=X1+(Width-Length)/2;
			lpwszTemp = (wchar_t*)xf_malloc((PosX-X1-4+Length+X2-PosX-Length-3+1)*sizeof(wchar_t));
			swprintf(lpwszTemp,PosX-X1-4+Length+X2-PosX-Length-3+1,L"%*ls%.*ls%*ls",PosX-X1-4,L"",Length,CPtrStr,X2-PosX-Length-3,L"");
			GotoXY(X1+4,Y1+I+2);
		}

		Text(lpwszTemp);
		xf_free(lpwszTemp);
	}

	/* $ 13.01.2003 IS
	   - Принудительно уберем запрет отрисовки экрана, если количество кнопок
	     в сообщении равно нулю и макрос закончил выполняться. Это необходимо,
	     чтобы заработал прогресс-бар от плагина, который был запущен при помощи
	     макроса запретом отрисовки (bugz#533).
	*/
	xf_free(Str);

	if (!Buttons)
	{
		if (ScrBuf.GetLockCount()>0 && !CtrlObject->Macro.PeekKey())
			ScrBuf.SetLockCount(0);

		ScrBuf.Flush();
	}

	return 0;
}