- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
808 lines
20 KiB
C++
808 lines
20 KiB
C++
//----------------------------------------------------------------------------
|
|
// ObjectWindows - (C) Copyright 1991, 1993 by Borland International
|
|
//----------------------------------------------------------------------------
|
|
#include <owl\owlpch.h>
|
|
#include <owl\dialog.h>
|
|
#include <owl\clipboar.h>
|
|
#include <owl\clipview.h>
|
|
#include "diagxprt.rh"
|
|
#include "setup.h"
|
|
#include "diagxprt.h"
|
|
#include <stdio.h>
|
|
|
|
//
|
|
// The diagnostic setup dialog box is divided in 2 main groups:
|
|
// * the system group (TSysGroup->TGroup);
|
|
// * the user group (TUsrGroup->TGroup).
|
|
//
|
|
// Each group is a list of items (TSetupItem).
|
|
// Items belonging to the system group (TSysItem->TSetupItem) are
|
|
// different than items belonging to the user group (TUsrItem->TSetupItem)
|
|
// in that the setup infos are not maintained the same way in OWL.INI.
|
|
//
|
|
// Each item TSysItem and TUsrItem is attached to a set of child windows
|
|
// in the dialog box. Each such set of windows is abstracted thru a class:
|
|
// TUsrWindow and TSysWindow respectively. Each of those classes is
|
|
// generated by a class template, which parametrizes the exact contents
|
|
// of the set of windows: TRadioButton/TRadioButton and TStatic/TEdit resp.
|
|
//
|
|
// The number of windows set is limited (by the area in the dialog box);
|
|
// the number of items is NOT limited. Scroll bars are displayed when
|
|
// necessary. Those scrollbars are abstracted thru the class TGroupScroll.
|
|
// Therefore each group maintains two arrays: an array of items TItemsArray
|
|
// and an array of window sets TWindowArray.
|
|
//
|
|
|
|
|
|
//
|
|
// Utility function to copy diagnostic code to clipboard so that user
|
|
// can paste into appropriate source file
|
|
//
|
|
void
|
|
CopyToClipboard(TWindow *w, char *descr, char *className)
|
|
{
|
|
// Generate a C++ example on the clipboard, which is a very trivial
|
|
// string subsitution operation.
|
|
//
|
|
string pattern(
|
|
"// Diagnostic: %s\n"
|
|
"DIAG_DEFINE_GROUP_INIT(OWL_INI, %s, 1, 0);\n"
|
|
"//TRACEX(%s, errLevel, \042A comment \042 << aFunction());\n"
|
|
);
|
|
|
|
pattern.substring("%s") = descr;
|
|
pattern.substring("%s") = className;
|
|
pattern.substring("%s") = className;
|
|
|
|
TClipboard& c = w->OpenClipboard();
|
|
c.EmptyClipboard();
|
|
HANDLE hData = GlobalAlloc(GMEM_SHARE, pattern.length()+1);
|
|
char far* pData = (char far*)GlobalLock(hData);
|
|
|
|
pattern.copy(pData, pattern.length()+1);
|
|
|
|
GlobalUnlock(hData);
|
|
c.SetClipboardData(CF_TEXT, hData);
|
|
|
|
c.CloseClipboard(); // Clipboard is responsible for freeing hData
|
|
}
|
|
|
|
//
|
|
// class TSetupItem
|
|
//
|
|
|
|
TSetupItem::TSetupItem(char *C, char *D) : Enable(0), level(0)
|
|
{
|
|
Class = C;
|
|
Descr = D;
|
|
}
|
|
|
|
void
|
|
TSetupItem::operator =(TBaseSetupWindow& w)
|
|
{
|
|
// Unmap from a physical set of windows: set the enability and
|
|
// warning level accordingly to the setup window:
|
|
//
|
|
SetEnable(w.GetEnable());
|
|
SetLevel(w.GetLevel());
|
|
}
|
|
|
|
void
|
|
TSetupItem::Load()
|
|
{
|
|
// Loads itself from .ini file - loads the diagnostic classname and the
|
|
// diagnostic description:
|
|
//
|
|
char b[80];
|
|
GetPrivateProfileString(GetSection(), Class.c_str(), "0 0",
|
|
b, sizeof(b), GetIniFile());
|
|
sscanf(b, "%d %d", &bEnable, &level);
|
|
if (Descr == "") {
|
|
GetPrivateProfileString(GetSectionDesc(), Class.c_str(), Class.c_str(),
|
|
b, sizeof(b), GetIniFile());
|
|
Descr = b;
|
|
}
|
|
}
|
|
|
|
void
|
|
TSetupItem::Save()
|
|
{
|
|
// Save itself to the .ini file - save the diagnostic classname and the
|
|
// diagnostic description:
|
|
//
|
|
char b[20];
|
|
sprintf(b, "%d %d", bEnable, level);
|
|
WritePrivateProfileString(GetSection(), Class.c_str(), b, GetIniFile());
|
|
WritePrivateProfileString(GetSectionDesc(), Class.c_str(), Descr.c_str(), GetIniFile());
|
|
}
|
|
|
|
//
|
|
// class TDiagEnable
|
|
//
|
|
|
|
DEFINE_RESPONSE_TABLE1(TDiagEnable, TCheckBox)
|
|
EV_NOTIFY_AT_CHILD(BN_CLICKED, BNClicked),
|
|
END_RESPONSE_TABLE;
|
|
|
|
// TDiagEnable provides an abstraction for the small check box associated
|
|
// to each setup item. This checkbox enables of disables the associated
|
|
// setup item. But the checkbox can itself be disabled (by a upper level
|
|
// checkbox).
|
|
//
|
|
void
|
|
TDiagEnable::BNClicked()
|
|
{
|
|
TCheckBox::BNClicked();
|
|
EnableWindow(TRUE);
|
|
}
|
|
|
|
BOOL
|
|
TDiagEnable::EnableWindow(BOOL enable)
|
|
{
|
|
BOOL ret = TCheckBox::EnableWindow(enable);
|
|
if (enable)
|
|
enable = GetCheck();
|
|
if (W0) W0->EnableWindow(enable);
|
|
if (W1) W1->EnableWindow(enable);
|
|
if (S0) S0->EnableWindow(enable);
|
|
if (S1) S1->EnableWindow(enable);
|
|
return ret;
|
|
}
|
|
|
|
//
|
|
// TMainEnable provides the abstraction for the main checkbox which
|
|
// enables of disables ALL the diagnostic groups. It knows how to save/load
|
|
// it state from the .ini file:
|
|
//
|
|
char* TMainEnable::Class = "Enabled";
|
|
|
|
TMainEnable::TMainEnable(TWindow* p, int n, TGroup* g1, TGroup* g2) :
|
|
TDiagEnable(p, n, g1, g2)
|
|
{
|
|
Create();
|
|
Load();
|
|
}
|
|
|
|
void
|
|
TMainEnable::Load()
|
|
{
|
|
char b[80];
|
|
GetPrivateProfileString(SYS_CLS, Class, "0", b, sizeof(b), SYS_INI);
|
|
SetCheck(atoi(b));
|
|
TDiagEnable::EnableWindow(TRUE);
|
|
}
|
|
|
|
void
|
|
TMainEnable::Save()
|
|
{
|
|
char b[80];
|
|
wsprintf(b, "%d", GetCheck() != 0);
|
|
WritePrivateProfileString(SYS_CLS, Class, b, SYS_INI);
|
|
}
|
|
|
|
|
|
//
|
|
// TGroup is the base class for diagnostic groups. TGroup knows how to
|
|
// enable/disable itself (by enabling/disabling all the associated setup
|
|
// items), to load/save from the .ini file and to map/unmap its setup
|
|
// items to the associated windows sets. The purpose of the map/unmap
|
|
// operations is to allow setup items to be scrolled.
|
|
//
|
|
|
|
void
|
|
TGroup::EnableWindow(BOOL bEnable)
|
|
{
|
|
for (int i = 0; i < Windows.GetItemsInContainer(); i++)
|
|
Windows[i]->EnableWindow(bEnable);
|
|
}
|
|
|
|
void
|
|
TGroup::Load()
|
|
{
|
|
for (int i = 0; i < Items.GetItemsInContainer(); i++)
|
|
Items[i]->Load();
|
|
}
|
|
|
|
void
|
|
TGroup::Save()
|
|
{
|
|
Cleanup();
|
|
for (int i = 0; i < Items.GetItemsInContainer(); i++)
|
|
Items[i]->Save();
|
|
}
|
|
|
|
int
|
|
TGroup::Map(int x)
|
|
{
|
|
// May have to re-validate <x>
|
|
//
|
|
if (x == MapAsBefore)
|
|
x = scrollPos;
|
|
if (x > Items.GetItemsInContainer() || x == MapToBottom)
|
|
x = Items.GetItemsInContainer() - Windows.GetItemsInContainer();
|
|
if (x < 0 || x == MapToTop)
|
|
x = 0;
|
|
scrollPos = x;
|
|
|
|
// Map each item to a window, as long as they fit
|
|
//
|
|
for (int i = 0; i < Windows.GetItemsInContainer(); i++, x++) {
|
|
if (x < Items.GetItemsInContainer()) {
|
|
*Windows[i] = *Items[x];
|
|
Windows[i]->EnableWindow(IsEnable());
|
|
} else
|
|
*Windows[i] = 0; // No more item: "empty" the associated window
|
|
}
|
|
return scrollPos;
|
|
}
|
|
|
|
int
|
|
TGroup::UnMap()
|
|
{
|
|
int i, x;
|
|
for (i = 0, x = scrollPos; i < Windows.GetItemsInContainer(); i++, x++) {
|
|
if (x < Items.GetItemsInContainer())
|
|
*Items[x] = *Windows[i];
|
|
}
|
|
return scrollPos;
|
|
}
|
|
|
|
|
|
//
|
|
// class TSysGroup
|
|
//
|
|
|
|
TSysGroup::TSysGroup(TWindow *Dialog, int nID)
|
|
{
|
|
// Create the child windows
|
|
//
|
|
for (int i = 0; Dialog->GetDlgItem(nID + i*4); i++)
|
|
Windows.Add(new TSysWindow(Dialog, nID + i*4));
|
|
|
|
// Create the predefined system items (read from resources)
|
|
//
|
|
HRSRC hRes = GetApplicationObject()->FindResource(IDR_SYS_ITEMS, RT_RCDATA);
|
|
if (hRes) {
|
|
HGLOBAL hData = GetApplicationObject()->LoadResource(hRes);
|
|
if (hData) {
|
|
LPSTR pData = (LPSTR)::LockResource(hData);
|
|
// pData now points to a set of strings
|
|
|
|
LPSTR pC = pData;
|
|
LPSTR pD;
|
|
|
|
while(pC && *pC) {
|
|
char name[128];
|
|
char desc[128];
|
|
pD = pC + strlen(pC) + 2;
|
|
lstrcpy(name, pC);
|
|
lstrcpy(desc, pD);
|
|
Items.Add(new TSysItem(name, desc));
|
|
pC = pD + strlen(pD) + 2;
|
|
}
|
|
#if !defined(__WIN32__)
|
|
::UnlockResource(hData);
|
|
#endif
|
|
}
|
|
#if !defined(__WIN32__)
|
|
::FreeResource(hData);
|
|
#endif
|
|
}
|
|
// Load the values associated to each item
|
|
TGroup::Load();
|
|
}
|
|
|
|
void
|
|
TSysGroup::Cleanup()
|
|
{
|
|
WritePrivateProfileString(SYS_CLS, 0, 0, SYS_INI);
|
|
WritePrivateProfileString(SYS_DSC, 0, 0, SYS_INI);
|
|
}
|
|
|
|
//
|
|
// class TUsrGroup
|
|
//
|
|
|
|
TUsrGroup::TUsrGroup(TWindow *Dialog, int nID)
|
|
{
|
|
// Create the child windows
|
|
//
|
|
for (int i = 0; Dialog->GetDlgItem(nID + i*4); i++)
|
|
Windows.Add(new TUsrWindow(Dialog, nID + i*4));
|
|
|
|
// Create the setup items (loaded from IniFile)
|
|
//
|
|
const int s = 4096;
|
|
char *p, *b = new char[s];
|
|
GetPrivateProfileString(USR_DSC, 0, "", b, s, USR_INI);
|
|
for (i = 0, p = b; p && *p; i++, p += strlen(p) + 1)
|
|
Items.Add(new TUsrItem(p));
|
|
delete b;
|
|
|
|
// Load the values associated to each item
|
|
//
|
|
TGroup::Load();
|
|
}
|
|
|
|
void
|
|
TUsrGroup::Cleanup()
|
|
{
|
|
// WritePrivateProfileString(USR_CLS, 0, 0, USR_INI);
|
|
WritePrivateProfileString(USR_DSC, 0, 0, USR_INI);
|
|
}
|
|
|
|
//
|
|
// TSizableDialog makes a dialog sizable. Two sizes are defined: a small
|
|
// size and a large size. Call the Toggle function to switch to any size.
|
|
// To determine the size, define a dummy control in the dialog which
|
|
// provides the upper-right corner of the small size.
|
|
// TSizableDialog also know how to center itself accordingly to the parent
|
|
// window, and how to re-adjust its position after being centered, if gone
|
|
// out of view.
|
|
//
|
|
|
|
void
|
|
TSizableDialog::SetupWindow()
|
|
{
|
|
TDialog::SetupWindow();
|
|
HWND hBox = GetDlgItem(nBoxID);
|
|
if (hBox) {
|
|
::ShowWindow(hBox, SW_HIDE);
|
|
TRect rSmall, rLarge;
|
|
::GetWindowRect(hBox, (LPRECT)&rSmall);
|
|
GetWindowRect(rLarge);
|
|
small.cx = rSmall.left - rLarge.left;
|
|
small.cy = rSmall.top - rLarge.top;
|
|
large = rLarge.Size();
|
|
tSize = t_max;
|
|
bMaximized = TRUE;
|
|
|
|
// Tolerate some inaccuracy on the positionning of the small box...
|
|
//
|
|
if (abs(small.cx - large.cx) < 4)
|
|
small.cx = large.cx;
|
|
if (abs(small.cy - large.cy) < 4)
|
|
small.cy = large.cy;
|
|
Toggle(t_min);
|
|
}
|
|
Center();
|
|
}
|
|
|
|
void
|
|
TSizableDialog::Toggle(int tType)
|
|
{
|
|
TSize newSize;
|
|
if (tType == t_minmax)
|
|
tType = (tSize == t_min) ? t_max : t_min;
|
|
|
|
tSize = tType;
|
|
switch (tType) {
|
|
case t_min:
|
|
newSize = small;
|
|
break;
|
|
case t_max:
|
|
newSize = large;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
bMaximized = tType != t_max;
|
|
SetWindowPos(0, TRect(TPoint(0, 0), newSize), SWP_NOZORDER|SWP_NOMOVE);
|
|
// EnableControls();
|
|
}
|
|
|
|
void
|
|
TSizableDialog::EnableControls()
|
|
{
|
|
TRect rParent = GetWindowRect();
|
|
HWND hChld = GetWindow(GW_CHILD);
|
|
while (hChld) {
|
|
POINT pt[2];
|
|
::GetWindowRect(hChld, (RECT*)&pt);
|
|
if (!PtInRect(&rParent, pt[0]))
|
|
::EnableWindow(hChld, 0);
|
|
hChld = ::GetWindow(hChld, GW_HWNDNEXT);
|
|
}
|
|
}
|
|
|
|
void
|
|
TSizableDialog::Center()
|
|
{
|
|
TRect rPar;
|
|
TRect rDlg;
|
|
GetWindowRect(rDlg);
|
|
HWND hParent = GetParent();
|
|
if (!hParent)
|
|
hParent = GetDesktopWindow();
|
|
::GetWindowRect(hParent, &rPar);
|
|
|
|
int wDlgWidth = rDlg.Width();
|
|
int wDlgHeight = (rDlg.bottom - rDlg.top);
|
|
|
|
int w = (rPar.right - rPar.left) - wDlgWidth;
|
|
int h = (rPar.bottom - rPar.top) - wDlgHeight;
|
|
|
|
int x = rPar.left + (w / 2);
|
|
int y = rPar.top + (h / 2);
|
|
|
|
MoveWindow(x, y, wDlgWidth , wDlgHeight, FALSE);
|
|
AdjustPos();
|
|
}
|
|
|
|
void
|
|
TSizableDialog::AdjustPos(void)
|
|
{
|
|
int W = GetSystemMetrics(SM_CXSCREEN);
|
|
int H = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
TRect r = GetWindowRect();
|
|
int w = r.Width();
|
|
int h = r.Height();
|
|
|
|
if (r.left < 0)
|
|
r.left = 0;
|
|
if (r.top < 0)
|
|
r.top = 0;
|
|
if (r.right > W)
|
|
r.left = W - w;
|
|
if (r.bottom > H)
|
|
r.top -= (H - h);
|
|
|
|
SetWindowPos(0, r.left, r.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|
|
|
|
|
|
//
|
|
// TGroupScroll provides the abstraction for a diagnostic group scrollbar.
|
|
// Associated to a diagnostic group, TGroupScroll simply map/unmap the
|
|
// diagnostic group on scroll events. It also knows how to hide itself when
|
|
// scrolling is irrelevant for that group (and show back if necessary):
|
|
|
|
DEFINE_RESPONSE_TABLE1(TGroupScroll, TScrollBar)
|
|
EV_WM_VSCROLL,
|
|
END_RESPONSE_TABLE;
|
|
|
|
TGroupScroll::TGroupScroll(TWindow* w, int i, TGroup* g)
|
|
: group(g), x(0), TScrollBar(w, i)
|
|
{
|
|
Create();
|
|
Initialize(0);
|
|
}
|
|
|
|
void
|
|
TGroupScroll::Initialize(int pos)
|
|
{
|
|
min = 0;
|
|
max = group->Items.GetItemsInContainer() - group->Windows.GetItemsInContainer();
|
|
|
|
if (max <= min)
|
|
ShowWindow(SW_HIDE); // Hide itself because scrolling is irrelevant
|
|
|
|
else {
|
|
SetRange(min, max);
|
|
TScrollBar::SetPosition(x = pos);
|
|
EndScroll();
|
|
PageMagnitude = group->Windows.GetItemsInContainer() - 1;
|
|
ShowWindow(SW_SHOW); // Show back itself, in case was previously hidden
|
|
}
|
|
}
|
|
|
|
void
|
|
TGroupScroll::EvVScroll(UINT code, UINT pos, HWND /*hCtl*/)
|
|
{
|
|
switch (code) {
|
|
case SB_LINEDOWN: if (x < max) SetPosition(x + LineMagnitude); break;
|
|
case SB_LINEUP: if (x > min) SetPosition(x - LineMagnitude); break;
|
|
case SB_PAGEDOWN: if (x < max) SetPosition(x + PageMagnitude); break;
|
|
case SB_PAGEUP: if (x > min) SetPosition(x - PageMagnitude); break;
|
|
case SB_THUMBPOSITION: SetPosition(pos); break;
|
|
case SB_ENDSCROLL: EndScroll(); break;
|
|
}
|
|
}
|
|
|
|
void
|
|
TGroupScroll::SetPosition(int pos)
|
|
{
|
|
x = pos;
|
|
if (x < min) x = min;
|
|
if (x > max) x = max;
|
|
TScrollBar::SetPosition(x);
|
|
|
|
// Perform the logical scroll by first unmaping the group and then
|
|
// by maping it to the new position:'
|
|
//
|
|
group->UnMap();
|
|
group->Map(x);
|
|
}
|
|
|
|
void
|
|
TGroupScroll::EndScroll()
|
|
{
|
|
::EnableScrollBar(*this, SB_CTL, ESB_ENABLE_BOTH);
|
|
if (x == min)
|
|
::EnableScrollBar(*this, SB_CTL, ESB_DISABLE_LTUP);
|
|
if (x == max)
|
|
::EnableScrollBar(*this, SB_CTL, ESB_DISABLE_RTDN);
|
|
if (::GetFocus()) {
|
|
::InvalidateRect(::GetFocus(), 0, TRUE);
|
|
::UpdateWindow(::GetFocus());
|
|
}
|
|
}
|
|
|
|
//
|
|
// TSetupDialog drives the setup diagnostic dialog box
|
|
//
|
|
|
|
DEFINE_RESPONSE_TABLE1(TSetupDialog, TDialog)
|
|
EV_COMMAND(IDC_MORE, CmZoom),
|
|
EV_COMMAND(IDOK, CmOk),
|
|
EV_COMMAND(IDC_ADD, CmAddUsr),
|
|
EV_COMMAND(IDC_DEL, CmDelUsr),
|
|
EV_COMMAND(IDC_EDT, CmEdtUsr),
|
|
END_RESPONSE_TABLE;
|
|
|
|
void
|
|
TSetupDialog::SetupWindow()
|
|
{
|
|
TSizableDialog::SetupWindow();
|
|
|
|
// Create the two groups:
|
|
//
|
|
SysGroup = new TSysGroup(this, ID_SYS_CHECK);
|
|
UsrGroup = new TUsrGroup(this, ID_USR_CHECK);
|
|
|
|
// Create the master enable switch and make it known to each group:
|
|
//
|
|
MainEnable = new TMainEnable(this, ID_SYS_ENABLE, SysGroup, UsrGroup);
|
|
SysGroup->SetMainSwitch(MainEnable);
|
|
UsrGroup->SetMainSwitch(MainEnable);
|
|
|
|
// Map each group to the first position:
|
|
//
|
|
SysGroup->Map(0);
|
|
UsrGroup->Map(0);
|
|
|
|
// Create the two group scrollbars and attach them to their groups:
|
|
//
|
|
SysScroll = new TGroupScroll(this, IDC_SYS_SCROLL, SysGroup);
|
|
UsrScroll = new TGroupScroll(this, IDC_USR_SCROLL, UsrGroup);
|
|
|
|
// Finally, create the actions buttons and update their enable states:
|
|
//
|
|
pDel = new TButton(this, IDC_DEL);
|
|
pDel->Create();
|
|
pEdt = new TButton(this, IDC_EDT);
|
|
pEdt->Create();
|
|
UpdateButtons();
|
|
}
|
|
|
|
void
|
|
TSetupDialog::CleanupWindow()
|
|
{
|
|
// Delete everybody
|
|
//
|
|
delete MainEnable;
|
|
delete UsrScroll;
|
|
delete SysScroll;
|
|
delete SysGroup;
|
|
delete UsrGroup;
|
|
delete pDel;
|
|
delete pEdt;
|
|
}
|
|
|
|
void
|
|
TSetupDialog::CmZoom()
|
|
{
|
|
// The uses clicked on the <More/Less> button: resize the dialog box
|
|
// and update the button title accordingly:
|
|
//
|
|
Toggle(TSizableDialog::t_minmax);
|
|
SetDlgItemText(IDC_MORE, !IsMaximized()? "<<< &Less" : "&More >>>");
|
|
}
|
|
|
|
void
|
|
TSetupDialog::CmOk()
|
|
{
|
|
// The user validated the changes: unmap to get the physical states and
|
|
// save each group:
|
|
//
|
|
SysGroup->UnMap();
|
|
UsrGroup->UnMap();
|
|
SysGroup->Save();
|
|
UsrGroup->Save();
|
|
MainEnable->Save();
|
|
TSizableDialog::CmOk();
|
|
}
|
|
|
|
void
|
|
TSetupDialog::CmAddUsr()
|
|
{
|
|
// The user selected the 'Add User Group' command. Execute the AddUser
|
|
// dialog box
|
|
//
|
|
TAddUsrDialog Dialog(this);
|
|
if (Dialog.Execute() == IDOK) {
|
|
// Unmap the user group to not lose the last changes, append
|
|
// the new user group to the end of the group and map the group
|
|
// by positionning to the bottom:
|
|
//
|
|
UsrGroup->UnMap();
|
|
UsrGroup->Items.Add(new TUsrItem(Dialog.Class, Dialog.Descr));
|
|
|
|
int x = UsrGroup->Map(TGroup::MapToBottom);
|
|
|
|
// Don't forget to reset the scrollbar:
|
|
//
|
|
if (UsrScroll)
|
|
UsrScroll->Initialize(x);
|
|
}
|
|
UpdateButtons();
|
|
}
|
|
|
|
void
|
|
TSetupDialog::CmDelUsr()
|
|
{
|
|
// The user selected the 'Delete User Group' command. Execute the DelUser
|
|
// dialog box
|
|
//
|
|
TDelUsrDialog Dialog(this, &UsrGroup->Items);
|
|
if (Dialog.Execute() == IDOK) {
|
|
// Unmap the user group to not lose the last changes, delete
|
|
// the chosen user group re-map the group:
|
|
//
|
|
int x = UsrGroup->UnMap();
|
|
UsrGroup->Items.Detach(Dialog.nSel);
|
|
x = UsrGroup->Map(x - 1);
|
|
|
|
// Don't forget to reset the scrollbar:
|
|
//
|
|
if (UsrScroll)
|
|
UsrScroll->Initialize(x);
|
|
}
|
|
UpdateButtons();
|
|
}
|
|
|
|
void
|
|
TSetupDialog::CmEdtUsr()
|
|
{
|
|
// The user selected the 'Edit User Group' command. Execute the EdtUser
|
|
// dialog box
|
|
//
|
|
TEdtUsrDialog Dialog(this, &UsrGroup->Items);
|
|
if (Dialog.Execute() == IDOK) {
|
|
UsrGroup->Map(TGroup::MapAsBefore);
|
|
}
|
|
}
|
|
|
|
void
|
|
TSetupDialog::UpdateButtons()
|
|
{
|
|
// Can only edit/delete not empty user group!
|
|
//
|
|
BOOL bEnable = UsrGroup->Items.GetItemsInContainer() > 0;
|
|
pDel->EnableWindow(bEnable);
|
|
pEdt->EnableWindow(bEnable);
|
|
}
|
|
|
|
//
|
|
// TAddUsrDialog: Prompts the user for two informations - a diagnostic
|
|
// classname and a diagnostic description. Require the classname and
|
|
// defaults the description to the classname.
|
|
//
|
|
|
|
DEFINE_RESPONSE_TABLE1(TAddUsrDialog, TDialog)
|
|
EV_COMMAND(IDOK, CmOk),
|
|
END_RESPONSE_TABLE;
|
|
|
|
void
|
|
TAddUsrDialog::CmOk()
|
|
{
|
|
::GetWindowText(GetDlgItem(IDC_DESCR), Descr, sizeof(Descr));
|
|
::GetWindowText(GetDlgItem(IDC_CLASS), Class, sizeof(Class));
|
|
if (!*Class) {
|
|
// Classname is required
|
|
//
|
|
MessageBox(
|
|
string(*GetModule(), IDS_ERR_ADD_TXT).c_str(),
|
|
string(*GetModule(), IDS_ERR_ADD_CAP).c_str(),
|
|
MB_OK|MB_ICONHAND);
|
|
::SetFocus(GetDlgItem(IDC_CLASS));
|
|
return;
|
|
}
|
|
if (!*Descr)
|
|
// Defaults the description to the classname
|
|
//
|
|
strcpy(Descr, Class);
|
|
|
|
// Put the template on the clipboard
|
|
//
|
|
CopyToClipboard(this, Descr, Class);
|
|
|
|
TDialog::CmOk();
|
|
}
|
|
|
|
//
|
|
// TItemsDialog: serves as a base class to the dialogs which need to
|
|
// show to the user a list of setup items. Know how to fill itself,
|
|
// given an array of setup items.
|
|
//
|
|
|
|
DEFINE_RESPONSE_TABLE1(TItemsDialog, TDialog)
|
|
EV_COMMAND(IDOK, CmOk),
|
|
EV_LBN_DBLCLK(IDC_LIST, LBDblClk),
|
|
EV_LBN_SELCHANGE(IDC_LIST, LBSelChange),
|
|
END_RESPONSE_TABLE;
|
|
|
|
void
|
|
TItemsDialog::SetupWindow()
|
|
{
|
|
CHECK(items != 0);
|
|
pList = new TListBox(this, IDC_LIST);
|
|
CHECK(pList != 0);
|
|
pList->Create();
|
|
for (int i = 0; i < items->GetItemsInContainer(); i++)
|
|
pList->AddString((*items)[i]->GetDescr());
|
|
}
|
|
|
|
TItemsDialog::~TItemsDialog() { delete pList; }
|
|
|
|
//
|
|
// TDelUsrDialog: animates the 'Delete User Group' dialog box. Just have
|
|
// to do the error handling, the base class doing the rest:
|
|
//
|
|
|
|
void
|
|
TDelUsrDialog::CmOk()
|
|
{
|
|
nSel = pList->GetSelIndex();
|
|
if (nSel == LB_ERR) {
|
|
MessageBox(
|
|
string(*GetModule(), IDS_ERR_DEL_TXT).c_str(),
|
|
string(*GetModule(), IDS_ERR_DEL_CAP).c_str(),
|
|
MB_OK|MB_ICONHAND);
|
|
::SetFocus(*pList);
|
|
} else
|
|
TItemsDialog::CmOk();
|
|
}
|
|
|
|
//
|
|
// TEdtUsrDialog: animates the 'edit User Group' dialog box. This enable
|
|
// the user to change classname/description of setup items after having
|
|
// created them. Also, generates on demand a C++ example on the clipboard:
|
|
//
|
|
|
|
|
|
DEFINE_RESPONSE_TABLE1(TEdtUsrDialog, TItemsDialog)
|
|
END_RESPONSE_TABLE;
|
|
|
|
void
|
|
TEdtUsrDialog::LBSelChange()
|
|
{
|
|
if (nPrevSel != LB_ERR) {
|
|
char Class[40], Descr[40];
|
|
GetDlgItemText(IDC_DESCR, Descr, sizeof(Descr));
|
|
GetDlgItemText(IDC_CLASS, Class, sizeof(Class));
|
|
(*items)[nPrevSel]->SetDescr(Descr);
|
|
(*items)[nPrevSel]->SetClass(Class);
|
|
pList->SetItemData(nPrevSel, (DWORD)Descr);
|
|
}
|
|
if ((nPrevSel = nSel = pList->GetSelIndex()) != LB_ERR) {
|
|
SetDlgItemText(IDC_DESCR, (*items)[nSel]->GetDescr());
|
|
SetDlgItemText(IDC_CLASS, (*items)[nSel]->GetClass());
|
|
}
|
|
}
|
|
|
|
void
|
|
TEdtUsrDialog::CmOk()
|
|
{
|
|
LBSelChange();
|
|
|
|
char descr[40], className[40];
|
|
|
|
GetDlgItemText(IDC_DESCR, descr, sizeof(descr));
|
|
GetDlgItemText(IDC_CLASS, className, sizeof(className));
|
|
CopyToClipboard(this, descr, className);
|
|
|
|
TItemsDialog::CmOk();
|
|
}
|