mirror of
https://github.com/microsoft/Microsoft-3D-Movie-Maker.git
synced 2024-11-25 11:42:35 +01:00
493 lines
11 KiB
C++
493 lines
11 KiB
C++
|
/* Copyright (c) Microsoft Corporation.
|
||
|
Licensed under the MIT License. */
|
||
|
|
||
|
/***************************************************************************
|
||
|
Author: ShonK
|
||
|
Project: Kauai
|
||
|
Reviewed:
|
||
|
Copyright (c) Microsoft Corporation
|
||
|
|
||
|
Mac standard dialogs.
|
||
|
|
||
|
***************************************************************************/
|
||
|
#include "frame.h"
|
||
|
ASSERTNAME
|
||
|
|
||
|
|
||
|
//REVIEW shonk: implement combo items.
|
||
|
|
||
|
/***************************************************************************
|
||
|
Read the dialog resource and construct the GGDIT.
|
||
|
***************************************************************************/
|
||
|
bool DLG::_FInit(void)
|
||
|
{
|
||
|
HN hn;
|
||
|
short ridDitl;
|
||
|
long sit, sitLim;
|
||
|
long idit;
|
||
|
byte bState;
|
||
|
byte *pbDitl;
|
||
|
byte bType;
|
||
|
long cbEntry;
|
||
|
DIT dit;
|
||
|
bool fAddDit;
|
||
|
bool fRet = fFalse;
|
||
|
|
||
|
if ((hn = (HN)GetResource('DLOG', (short)_rid)) == hNil)
|
||
|
{
|
||
|
PushErc(ercDlgCantFind);
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
//get the rid of the DITL resource
|
||
|
ridDitl = (*(short **)hn)[9];
|
||
|
if ((hn = GetResource('DITL', ridDitl)) == hNil)
|
||
|
{
|
||
|
PushErc(ercDlgCantFind);
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
//lock the DITL so it doesn't move and so it isn't purged while
|
||
|
//we're looking at it.
|
||
|
bState = HGetState(hn);
|
||
|
HLock(hn);
|
||
|
pbDitl = *(byte **)hn;
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
This info comes from New Inside Macintosh - Toolbox Essentials,
|
||
|
pages 6-152 to 6-156.
|
||
|
|
||
|
A DITL is a group of items preceeded by a short containing the number
|
||
|
of items - 1. Each item contains:
|
||
|
|
||
|
4 bytes of reserved info
|
||
|
8 bytes for a bounding rectangle
|
||
|
1 byte for the item type and enable flag
|
||
|
|
||
|
The remaining data in the item depends on the type of item. For
|
||
|
Buttons(4), checkboxes(5), radio buttons(6), static text(8) and
|
||
|
editable text items(16), the item data continues with:
|
||
|
|
||
|
1 - 256 bytes (variable) - an st containing the name
|
||
|
0 or 1 byte alignment (to a short word)
|
||
|
|
||
|
For compiled controls(7), icons(32) and pictures(64):
|
||
|
|
||
|
1 byte reserved
|
||
|
2 bytes resource number
|
||
|
|
||
|
For application defined items(0):
|
||
|
|
||
|
1 byte reserved
|
||
|
|
||
|
For Help items(1):
|
||
|
|
||
|
1 byte size - 4 or 6 (so we don't have to use the help item type)
|
||
|
2 byte help item type
|
||
|
2 byte resource number
|
||
|
0 or 2 bytes for an item number (2 bytes if help item type is 8,
|
||
|
otherwise 0 bytes)
|
||
|
|
||
|
For other values of the item type, we assert and bag out.
|
||
|
***********************************************************************/
|
||
|
|
||
|
//get the lim of system items (they start at 1) and grow the GGDIT
|
||
|
//to a reasonable size
|
||
|
sitLim = (*(short *)pbDitl) + 2;
|
||
|
pbDitl += size(short);
|
||
|
if (!FEnsureSpace(sitLim, size(long), fgrpNil))
|
||
|
goto LFail;
|
||
|
|
||
|
//look at the items in the DITL
|
||
|
for (idit = 0, sit = 1; sit < sitLim; sit++)
|
||
|
{
|
||
|
//skip the reserved bytes and rectangle
|
||
|
pbDitl += 12;
|
||
|
|
||
|
//the high bit is an enble bit, so mask it off
|
||
|
bType = *pbDitl & 0x7F;
|
||
|
pbDitl++;
|
||
|
|
||
|
fAddDit = fFalse;
|
||
|
switch (bType)
|
||
|
{
|
||
|
default:
|
||
|
Bug("unkown item in DITL resource");
|
||
|
goto LFail;
|
||
|
|
||
|
case btnCtrl + ctrlItem: //button
|
||
|
dit.ditk = ditkButton;
|
||
|
cbEntry = 0;
|
||
|
fAddDit = fTrue;
|
||
|
goto LSkipSt;
|
||
|
|
||
|
case chkCtrl + ctrlItem: //check box
|
||
|
dit.ditk = ditkCheckBox;
|
||
|
cbEntry = size(long);
|
||
|
fAddDit = fTrue;
|
||
|
goto LSkipSt;
|
||
|
|
||
|
case radCtrl + ctrlItem: //radio button
|
||
|
//if the last item added was a radio group, add this button to
|
||
|
//the group, otherwise create a new radio group
|
||
|
if (idit > 0)
|
||
|
{
|
||
|
GetDit(idit - 1, &dit);
|
||
|
if (dit.ditk == ditkRadioGroup && dit.sitLim == sit)
|
||
|
{
|
||
|
dit.sitLim++;
|
||
|
PutDit(idit - 1, &dit);
|
||
|
goto LSkipSt;
|
||
|
}
|
||
|
}
|
||
|
dit.ditk = ditkRadioGroup;
|
||
|
cbEntry = size(long);
|
||
|
fAddDit = fTrue;
|
||
|
goto LSkipSt;
|
||
|
|
||
|
case statText: //static text item
|
||
|
goto LSkipSt;
|
||
|
|
||
|
case editText: //edit item
|
||
|
dit.ditk = ditkEditText;
|
||
|
cbEntry = kcbMaxStz - kcchMaxStz;
|
||
|
fAddDit = fTrue;
|
||
|
LSkipSt:
|
||
|
pbDitl += CbSt((achar *)pbDitl);
|
||
|
if ((long)pbDitl & 1)
|
||
|
pbDitl++;
|
||
|
break;
|
||
|
|
||
|
case 7: //control
|
||
|
case iconItem: //icon
|
||
|
case picItem: //picture
|
||
|
pbDitl += 3;
|
||
|
break;
|
||
|
|
||
|
case userItem: //app defined
|
||
|
pbDitl += 1;
|
||
|
break;
|
||
|
|
||
|
case 1: //help item
|
||
|
pbDitl += CbSt((achar *)pbDitl);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (fAddDit)
|
||
|
{
|
||
|
Assert(cbEntry >= 0, 0);
|
||
|
dit.sitMin = sit;
|
||
|
dit.sitLim = sit + 1;
|
||
|
if (!FInsert(idit, cbEntry, pvNil, &dit))
|
||
|
goto LFail;
|
||
|
|
||
|
//zero the extra data
|
||
|
if (cbEntry > 0)
|
||
|
ClearPb(QvGet(idit), cbEntry);
|
||
|
idit++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FEnsureSpace(0, 0, fgrpShrink);
|
||
|
fRet = fTrue;
|
||
|
|
||
|
LFail:
|
||
|
HSetState(hn, bState);
|
||
|
if (!fRet)
|
||
|
PushErc(ercDlgOom);
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Actually put up the dialog and don't return until it comes down.
|
||
|
Returns the idit that dismissed the dialog. Returns ivNil on failure.
|
||
|
***************************************************************************/
|
||
|
long DLG::IditDo(long iditFocus)
|
||
|
{
|
||
|
HDLG hdlg;
|
||
|
DIT dit;
|
||
|
short swHit;
|
||
|
long idit = ivNil;
|
||
|
|
||
|
if ((hdlg = GetNewDialog((short)_rid, pvNil, (PPRT)-1L)) == pvNil)
|
||
|
{
|
||
|
PushErc(ercDlgOom);
|
||
|
goto LDone;
|
||
|
}
|
||
|
|
||
|
if (pvNil == (_pgob = NewObj GOB(khidDialog)))
|
||
|
{
|
||
|
PushErc(ercDlgOom);
|
||
|
goto LDone;
|
||
|
}
|
||
|
|
||
|
if (!_pgob->FAttachHwnd((HWND)hdlg))
|
||
|
{
|
||
|
PushErc(ercDlgOom);
|
||
|
goto LDone;
|
||
|
}
|
||
|
|
||
|
SetValues(0, IvMac());
|
||
|
ShowWindow(hdlg);
|
||
|
if (ivNil != iditFocus)
|
||
|
SelectDit(iditFocus);
|
||
|
for (;;)
|
||
|
{
|
||
|
ModalDialog(pvNil, &swHit);
|
||
|
if ((idit = IditFromSit((long)swHit)) == ivNil)
|
||
|
continue;
|
||
|
|
||
|
GetDit(idit, &dit);
|
||
|
switch (dit.ditk)
|
||
|
{
|
||
|
default:
|
||
|
continue;
|
||
|
|
||
|
case ditkButton:
|
||
|
break;
|
||
|
|
||
|
case ditkCheckBox:
|
||
|
//invert it
|
||
|
_InvertCheckBox(idit);
|
||
|
break;
|
||
|
|
||
|
case ditkRadioGroup:
|
||
|
//set the value to swHit - dit.sitMin
|
||
|
_SetRadioGroup(idit, (long)swHit - dit.sitMin);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (_FDitChange(&idit))
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
LDone:
|
||
|
if (hdlg != hNil)
|
||
|
{
|
||
|
if (_pgob != pvNil)
|
||
|
{
|
||
|
if (idit != ivNil && !FGetValues(0, IvMac()))
|
||
|
{
|
||
|
PushErc(ercDlgCantGetArgs);
|
||
|
idit = ivNil;
|
||
|
}
|
||
|
_pgob->FAttachHwnd(hNil);
|
||
|
_pgob->Release();
|
||
|
_pgob = pvNil;
|
||
|
}
|
||
|
DisposeDialog(hdlg);
|
||
|
}
|
||
|
|
||
|
return idit;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Get the value of a radio group.
|
||
|
***************************************************************************/
|
||
|
long DLG::_LwGetRadioGroup(long idit)
|
||
|
{
|
||
|
HDLG hdlg;
|
||
|
DIT dit;
|
||
|
short sitk;
|
||
|
HCTL hctl;
|
||
|
RCS rcs;
|
||
|
long sit;
|
||
|
|
||
|
GetDit(idit, &dit);
|
||
|
hdlg = (HDLG)_pgob->Hwnd();
|
||
|
Assert(hdlg != hNil, "no dialog!");
|
||
|
Assert(dit.ditk == ditkRadioGroup, "not a radio group!");
|
||
|
|
||
|
for (sit = dit.sitMin; sit < dit.sitLim; sit++)
|
||
|
{
|
||
|
GetDialogItem(hdlg, (short)sit, &sitk, (HN *)&hctl, &rcs);
|
||
|
Assert(sitk == (radCtrl + ctrlItem), "not a radio button!");
|
||
|
if (GetCtlValue(hctl))
|
||
|
return sit - dit.sitMin;
|
||
|
}
|
||
|
Bug("no radio button set");
|
||
|
return dit.sitLim - dit.sitMin;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Change a radio group value.
|
||
|
***************************************************************************/
|
||
|
void DLG::_SetRadioGroup(long idit, long lw)
|
||
|
{
|
||
|
HDLG hdlg;
|
||
|
DIT dit;
|
||
|
short sitk;
|
||
|
HCTL hctl;
|
||
|
RCS rcs;
|
||
|
long sit;
|
||
|
short swT;
|
||
|
|
||
|
GetDit(idit, &dit);
|
||
|
hdlg = (HDLG)_pgob->Hwnd();
|
||
|
Assert(hdlg != hNil, "no dialog!");
|
||
|
Assert(dit.ditk == ditkRadioGroup, "not a radio group!");
|
||
|
AssertIn(lw, 0, dit.sitLim - dit.sitMin);
|
||
|
|
||
|
GNV gnv(_pgob);
|
||
|
gnv.Set();
|
||
|
for (sit = dit.sitMin; sit < dit.sitLim; sit++)
|
||
|
{
|
||
|
GetDialogItem(hdlg, (short)sit, &sitk, (HN *)&hctl, &rcs);
|
||
|
Assert(sitk == (radCtrl + ctrlItem), "not a radio button!");
|
||
|
swT = GetCtlValue(hctl);
|
||
|
|
||
|
//set the value
|
||
|
if (swT)
|
||
|
{
|
||
|
if (sit - dit.sitMin != lw)
|
||
|
SetCtlValue(hctl, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (sit - dit.sitMin == lw)
|
||
|
SetCtlValue(hctl, 1);
|
||
|
}
|
||
|
}
|
||
|
gnv.Restore();
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Returns the current value of a check box.
|
||
|
***************************************************************************/
|
||
|
bool DLG::_FGetCheckBox(long idit)
|
||
|
{
|
||
|
HDLG hdlg;
|
||
|
DIT dit;
|
||
|
short sitk;
|
||
|
HCTL hctl;
|
||
|
RCS rcs;
|
||
|
|
||
|
GetDit(idit, &dit);
|
||
|
hdlg = (HDLG)_pgob->Hwnd();
|
||
|
Assert(hdlg != hNil, "no dialog!");
|
||
|
Assert(dit.ditk == ditkCheckBox, "not a check box!");
|
||
|
Assert(dit.sitLim == dit.sitMin + 1, "wrong lim on check box");
|
||
|
|
||
|
GetDialogItem(hdlg, (short)dit.sitMin, &sitk, (HN *)&hctl, &rcs);
|
||
|
Assert(sitk == (chkCtrl + ctrlItem), "not a check box!");
|
||
|
return FPure(GetCtlValue(hctl));
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Invert the value of a check box.
|
||
|
***************************************************************************/
|
||
|
void DLG::_InvertCheckBox(long idit)
|
||
|
{
|
||
|
_SetCheckBox(idit, !_FGetCheckBox(idit));
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Set the value of a check box.
|
||
|
***************************************************************************/
|
||
|
void DLG::_SetCheckBox(long idit, bool fOn)
|
||
|
{
|
||
|
HDLG hdlg;
|
||
|
DIT dit;
|
||
|
short sitk;
|
||
|
HCTL hctl;
|
||
|
RCS rcs;
|
||
|
short swT;
|
||
|
|
||
|
GetDit(idit, &dit);
|
||
|
hdlg = (HDLG)_pgob->Hwnd();
|
||
|
Assert(hdlg != hNil, "no dialog!");
|
||
|
Assert(dit.ditk == ditkCheckBox, "not a check box!");
|
||
|
Assert(dit.sitLim == dit.sitMin + 1, "wrong lim on check box");
|
||
|
|
||
|
GNV gnv(_pgob);
|
||
|
gnv.Set();
|
||
|
GetDialogItem(hdlg, (short)dit.sitMin, &sitk, (HN *)&hctl, &rcs);
|
||
|
Assert(sitk == (chkCtrl + ctrlItem), "not a check box!");
|
||
|
swT = GetCtlValue(hctl);
|
||
|
if (FPure(swT) != FPure(fOn))
|
||
|
SetCtlValue(hctl, FPure(fOn));
|
||
|
gnv.Restore();
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Get the text from an edit control.
|
||
|
***************************************************************************/
|
||
|
void DLG::_GetEditText(long idit, PSTZ pstz)
|
||
|
{
|
||
|
HDLG hdlg;
|
||
|
DIT dit;
|
||
|
short sitk;
|
||
|
HN hn;
|
||
|
RCS rcs;
|
||
|
|
||
|
GetDit(idit, &dit);
|
||
|
hdlg = (HDLG)_pgob->Hwnd();
|
||
|
Assert(hdlg != hNil, "no dialog!");
|
||
|
Assert(dit.ditk == ditkEditText, "not edit item!");
|
||
|
Assert(dit.sitLim == dit.sitMin + 1, "wrong lim on edit item");
|
||
|
|
||
|
GetDialogItem(hdlg, (short)dit.sitMin, &sitk, &hn, &rcs);
|
||
|
AssertVar(sitk == editText, "not an edit item!", &sitk);
|
||
|
GetDialogItemText(hn, (byte *)pstz);
|
||
|
StToStz(pstz);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Set the text in an edit control.
|
||
|
***************************************************************************/
|
||
|
void DLG::_SetEditText(long idit, PSTZ pstz)
|
||
|
{
|
||
|
HDLG hdlg;
|
||
|
DIT dit;
|
||
|
short sitk;
|
||
|
HN hn;
|
||
|
RCS rcs;
|
||
|
|
||
|
GetDit(idit, &dit);
|
||
|
hdlg = (HDLG)_pgob->Hwnd();
|
||
|
Assert(hdlg != hNil, "no dialog!");
|
||
|
Assert(dit.ditk == ditkEditText, "not edit item!");
|
||
|
Assert(dit.sitLim == dit.sitMin + 1, "wrong lim on edit item");
|
||
|
|
||
|
GNV gnv(_pgob);
|
||
|
gnv.Set();
|
||
|
GetDialogItem(hdlg, (short)dit.sitMin, &sitk, &hn, &rcs);
|
||
|
AssertVar(sitk == editText, "not an edit item!", &sitk);
|
||
|
SetDialogItemText(hn, (byte *)pstz);
|
||
|
gnv.Restore();
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Make the given item the "focused" item and select its contents. The
|
||
|
item should be a text item.
|
||
|
***************************************************************************/
|
||
|
void DLG::SelectDit(long idit)
|
||
|
{
|
||
|
HDLG hdlg;
|
||
|
DIT dit;
|
||
|
|
||
|
if (hNil == (hdlg = (HDLG)_pgob->Hwnd()))
|
||
|
goto LBug;
|
||
|
|
||
|
GetDit(idit, &dit);
|
||
|
if (dit.ditk != ditkEditText)
|
||
|
{
|
||
|
LBug:
|
||
|
Bug("bad call to DLG::SelectDit");
|
||
|
return;
|
||
|
}
|
||
|
Assert(dit.sitLim == dit.sitMin + 1, "wrong lim on edit item");
|
||
|
SelIText(hdlg, (short)dit.sitMin, 0, kswMax);
|
||
|
}
|
||
|
|