home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GCW Games & More & Wacky Windows Companion
/
gcw.iso
/
win
/
util
/
mygroups
/
grpfile.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-06-29
|
15KB
|
434 lines
Unit GrpFile;
{This unit provides various functions to read data from the Windows
group files}
Interface
Uses WinTypes;
Type IconEnum = Procedure(Icon:hIcon);
Function GetIcon(Group:PChar; Index:Integer):hIcon;
Procedure EnumIcons(Group:PChar; EnumProc:IconEnum);
Function GetGroupName(Description:PChar; GroupName:PChar; Len:Word):PChar;
Function GetGroupDDE(Group:PChar):PChar;
Implementation
Uses WinProcs, Strings;
Type tagGroupHeader = Record {Group file fixed length header}
identifier:Array [0..3] of Char; {always 'PMCC'}
wCheckSum:Word; {file checksum}
cbGroup:Word; {size of Windows 3.0 compatible
portion of file. In Win 3.1 it is the offset to the tagdata.}
nCmdShow:Word; {Normal, minimized, maximized}
rcNormal:TRect; {Rectangle for show normal}
ptMin:TPoint; {Point for show minimized}
pName:Word; {Offset of description}
wLogPixelsX:Word; {Width of icon}
wLogPixelsY:Word; {Height of icon}
Case Boolean of
False: (wBitsperPixel:Word; {Windows 3.0}
wPlanes:Word; {Windows 3.0}
cItems:Word); {Windows 3.0 & 3.1} {Number of items
in the griItems array}
True: (bBitsperPixel:Byte; {Windows 3.1}
bPlanes:Byte; {Windows 3.1}
cItems31:Word; {Windows 3.0 & 3.1 duplicates cItems}
Reserved:Word);
{rgiItems:Array [0..cItems-1] of Word;} {array of offsets to tagItemInfo items}
End;
Type tagItemInfo = Record {Data for an individual program}
pt:TPoint; {Point for program icon}
iIcon:Word; {Index of icon in icon file}
cbHeader:Word; {Size of tagCURSORSHAPE}
cbANDPlane:Word; {Size of AND bits for icon}
cbXORPlane:Word; {Size of XOR bits for icon}
pHeader:Word; {Offset of a tagCURSORSHAPE}
pANDPlane:Word; {Offset of AND bits for icon}
pXORPlane:Word; {Offset of XOR bits for icon}
pName:Word; {Offset of description of program}
pCommand:Word; {Offset of command line for program}
pIconPath:Word; {Offset of icon file name}
End;
Type tagCURSORSHAPE = Record {Info about icon for a program}
xHotSpot:Integer; {Always 0}
yHotSpot:Integer; {Always 0}
cx:Integer; {width of program icon}
cy:Integer; {height of program icon}
cbWidth:Integer; {Bytes of data per row
accounting for WORD alignment.}
bPlanes:Byte; {Number of display planes for icon}
bBitsPixel:Byte; {Bits per pixel for icon}
End;
Type tagTAGDATA = Record {Windows 3.1 auxillary info}
wID:Word; { $8101 for path, $8102 for hotkey, $8103 for minimized}
{ $8000 for first tagdata; path element of 'PMCC'}
{ $FFFF for last tagdata}
wItem:Word; {Program index that tag refers to}
cb:Word; {Size of TAGDATA data structure}
Case Boolean of
False: (Path:Array [0..255] of Char); {Path}
True: (HotKey:Word); {Program hotkey}
End;
Type WArray = Array [0..0] of Word;
Type PArray = ^WArray;
Var GroupHeader:tagGroupHeader;
ItemInfo:tagItemInfo;
CursorShape:tagCURSORSHAPE;
TagData:tagTAGDATA;
Grp:File;
rgiItems:PArray;
Function OpenGroup(FName:PChar):Integer;
{Internal function. Opens a group file, loads the fixed header (GroupHeader)
and loads the variable length header (rgiItems).
Returns 0 if everything OK.
Input: FName - Name of group file}
Var OldFileMode:Byte;
Result:Integer;
Len,I,J:Word;
Begin
OldFileMode:=FileMode;
FileMode:=0;
Assign(Grp,FName);
{$I-} Reset(Grp,1); {$I+}
Result:=IOResult;
OpenGroup:=Result;
FileMode:=OldFileMode;
If Result = 0 then
Begin {Read the fixed header}
BlockRead(Grp,GroupHeader,Sizeof(GroupHeader),Len);
If (Len <> Sizeof(GroupHeader)) or
(StrLComp(GroupHeader.identifier,'PMCC',4) <> 0)then
{If I wanted to be really rigorous here, I could read the entire
file as WORD items and the sum should be zero. The wCheckSum word
is adjusted to insure this.}
Begin
OpenGroup:=1;
Close(Grp);
Exit;
End;
rgiItems:=Nil; {Now load the variable length header section}
If GroupHeader.cItems = 0 then Exit;
GetMem(rgiItems,GroupHeader.cItems*Sizeof(Word));
BlockRead(Grp,rgiItems^,GroupHeader.cItems*Sizeof(Word),Len);
If Len <> GroupHeader.cItems*Sizeof(Word) then
Begin
OpenGroup:=1;
Close(Grp);
FreeMem(rgiItems,GroupHeader.cItems*Sizeof(Word));
rgiItems:=Nil;
Exit;
End;
End;
End;
Procedure CloseGroup;
{Internal procedure. Closes the group file and frees any memory allocated
by OpenGroup.}
Begin
If rgiItems <> Nil then
FreeMem(rgiItems,GroupHeader.cItems*Sizeof(Word));
Close(Grp);
End;
Function ReadIcon(Index:Word):hIcon;
{Internal function. Loads an icon from the group file.
Returns the handle of the icon.
Input: Index - the index in rgiItems of the program for which to load
the icon}
Var ANDBits,XORBits:Pointer;
Len:Word;
Begin
ReadIcon:=0;
If (rgiItems = Nil) or (rgiItems^[Index] = 0) then Exit;
Seek(Grp,rgiItems^[Index]);
BlockRead(Grp,ItemInfo,Sizeof(ItemInfo),Len);
If Len <> Sizeof(ItemInfo) then Exit;
Seek(Grp,ItemInfo.pHeader);
Blockread(Grp,CursorShape,Sizeof(CursorShape),Len);
If Len <> Sizeof(CursorShape) then Exit;
GetMem(ANDBits,ItemInfo.cbANDPlane);
GetMem(XORBits,ItemInfo.cbXORPlane);
Seek(Grp,ItemInfo.pANDPlane);
BlockRead(Grp,ANDBits^,ItemInfo.cbANDPlane,Len);
If Len = ItemInfo.cbANDPlane then
Begin
Seek(Grp,ItemInfo.pXORPlane);
BlockRead(Grp,XORBits^,ItemInfo.cbXORPlane,Len);
If Len = ItemInfo.cbXORPlane then
ReadIcon:=CreateIcon(hInstance,CursorShape.cx,
CursorShape.cy,CursorShape.bPlanes,
CursorShape.bBitsPixel,ANDBits,XORBits);
End;
FreeMem(XORBits,ItemInfo.cbXORPlane);
FreeMem(ANDBits,ItemInfo.cbANDPlane);
End;
Function GetProgramPath(Index:Word):PChar;
{Internal function. Returns a pointer to the program path if found,
else returns a pointer to an empty string.
Input: Index - The index of the program item}
Var Len:Integer;
Begin
GetProgramPath:=@TagData.Path;
Seek(Grp,GroupHeader.cbGroup);
BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
While (Len = (Sizeof(TagData)-Sizeof(TagData.Path))) and
(TagData.wID <> $FFFF) do
Begin
If TagData.cb > Sizeof(TagData)-Sizeof(TagData.Path) then
BlockRead(Grp,TagData.Path,TagData.cb-(Sizeof(TagData)-Sizeof(TagData.Path)),Len);
If (TagData.wID = $8101) and (TagData.wItem = Index) then
Len:=0
else
BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
End;
If (TagData.wID <> $8101) or (TagData.wItem <> Index) then
TagData.Path[0]:=#0;
End;
Function GetProgramHotKey(Index:Word):Word;
{Internal function. Returns the hotkey for the program if found else zero.
Input: Index - The index of the program item}
Var Len:Integer;
Begin
GetProgramHotKey:=0;
Seek(Grp,GroupHeader.cbGroup);
BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
While (Len = (Sizeof(TagData)-Sizeof(TagData.Path))) and
(TagData.wID <> $FFFF) do
Begin
If TagData.cb > Sizeof(TagData)-Sizeof(TagData.Path) then
BlockRead(Grp,TagData.Path,TagData.cb-(Sizeof(TagData)-Sizeof(TagData.Path)),Len);
If (TagData.wID = $8102) and (TagData.wItem = Index) then
Begin
GetProgramHotKey:=TagData.HotKey;
Len:=0;
End
else
BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
End;
End;
Function GetProgramMinFlag(Index:Word):Boolean;
{Internal function. Returns TRUE if the program runs minimized.
Input: Index - The index of the program item}
Var Len:Integer;
Begin
GetProgramMinFlag:=False;
Seek(Grp,GroupHeader.cbGroup);
BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
While (Len = (Sizeof(TagData)-Sizeof(TagData.Path))) and
(TagData.wID <> $FFFF) do
Begin
If TagData.cb > Sizeof(TagData)-Sizeof(TagData.Path) then
BlockRead(Grp,TagData.Path,TagData.cb-(Sizeof(TagData)-Sizeof(TagData.Path)),Len);
If (TagData.wID = $8103) and (TagData.wItem = Index) then
Begin
GetProgramMinFlag:=True;
Len:=0;
End
else
BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
End;
End;
Function GetIcon(Group:pChar; Index:Integer):hIcon;
{External function. Loads an icon from a group file.
Returns the handle to the icon.
Input: Group - The name of the group file
Index - The index in rgiItems of the program icon}
Begin
GetIcon:=0;
If OpenGroup(Group) <> 0 then Exit;
If GroupHeader.cItems > Index then
GetIcon:=ReadIcon(Index);
CloseGroup;
End;
Procedure EnumIcons(Group:PChar; EnumProc:IconEnum);
{External procedure. Calls a procedure for each icon in the group file.
Input: Group - The name of the group file
EnumProc - The address of the procedure to call. It must have the
format: Procedure EnumProc(Icon:hIcon); Far; }
Var I:Word;
Icon:hIcon;
Begin
If OpenGroup(Group) <> 0 then Exit;
If rgiItems <> Nil then
For I:=0 to GroupHeader.cItems-1 do
If rgiItems^[I] <> 0 then
Begin
Icon:=ReadIcon(I);
If Icon <> 0 then
Begin
EnumProc(Icon);
DestroyIcon(Icon);
End;
End;
CloseGroup;
End;
Function GetGroupName(Description:PChar; GroupName:PChar; Len:Word):PChar;
{External function. Takes a group description and find the corresponding
group file. Returns a pointer to the group file name.
Input: Description - The description under the group icon in the
Program Manager
Len - The length of the output array
Output: GroupName - The output array which receives the file name}
Var PG,PGroup,PDesc,FName:PChar;
I,J,K:Word;
Begin
GroupName[0]:=#0;
GetGroupName:=GroupName;
I:=500;
GetMem(PGroup,I);
While GetPrivateProfileString('Groups',Nil,'',PGroup,I,'PROGMAN.INI') = I-1 do
Begin
Freemem(PGroup,I);
Inc(I,500);
GetMem(PGroup,I);
End;
J:=StrLen(Description)+1;
GetMem(PDesc,J+1);
GetMem(FName,256);
PG:=PGroup;
While (PG^ <> #0) and (GroupName^ = #0) do
Begin
If (GetPrivateProfileString('Groups',PG,'',FName,256,'PROGMAN.INI') > 0) and
(OpenGroup(FName) = 0) then
Begin
Seek(Grp,GroupHeader.pName);
BlockRead(Grp,PDesc^,J,K);
PDesc[K]:=#0;
If StrComp(PDesc,Description) = 0 then
StrLCopy(GroupName,FName,Len);
CloseGroup;
End;
Inc(PG,StrLen(PG)+1);
End;
FreeMem(FName,256);
FreeMem(PDesc,J+1);
FreeMem(PGroup,I);
End;
Function GetGroupDDE(Group:PChar):PChar;
{External function. This function returns a pointer to a memory area which
receives data in a format similar (but not quite identical) to the Windows
3.1 Program Manager DDE interface for a particular group. This function
will work with Windows 3.0, which does not support that particular
DDE interface. It is up to the caller to do a StrDispose on the array.
Input: Group - The name of the group file}
Var PDDE,PFinal:PChar;
I,J,Len:Word;
Procedure Str(I:Word; P:PChar);
Var S:String [10];
Begin
System.Str(I,S);
StrPCopy(P,S);
End;
Begin
GetGroupDDE:=Nil;
If OpenGroup(Group) <> 0 then Exit;
GetMem(PDDE,(GroupHeader.cItems+1)*1024);
If PDDE = Nil then
Begin
CloseGroup;
Exit;
End;
StrCopy(PDDE,'"');
Seek(Grp,GroupHeader.pName);
BlockRead(Grp,StrEnd(PDDE)^,256,Len);
StrCat(PDDE,'",');
StrCat(PDDE,Group);
StrCat(PDDE,',');
PFinal:=StrEnd(PDDE);
I:=GroupHeader.cItems;
If I > 0 then
For J:=0 to I-1 do
If rgiItems^[J] = 0 then Dec(I);
Str(I,PFinal);
StrCat(PFinal,',');
Str(GroupHeader.ptMin.Y,StrEnd(PFinal));
StrCat(PFinal,^M^J);
If GroupHeader.cItems > 0 then
For I:=0 to GroupHeader.cItems-1 do
If rgiItems^[I] <> 0 then
Begin
Seek(Grp,rgiItems^[I]);
BlockRead(Grp,ItemInfo,Sizeof(ItemInfo),Len);
If Len <> Sizeof(ItemInfo) then
Begin
FreeMem(PDDE,(GroupHeader.cItems+1)*1024);
CloseGroup;
Exit;
End;
PFinal:=StrEnd(PFinal);
StrCat(PFinal,'"');
Seek(Grp,ItemInfo.pName);
BlockRead(Grp,StrEnd(PFinal)^,256,Len);
StrCat(PFinal,'","');
Seek(Grp,ItemInfo.PCommand);
BlockRead(Grp,StrEnd(PFinal)^,256,Len);
StrCat(PFinal,'",');
StrCat(PFinal,GetProgrampath(I));
StrCat(PFinal,',');
Seek(Grp,ItemInfo.pIconPath);
BlockRead(Grp,StrEnd(PFinal)^,256,Len);
StrCat(PFinal,',');
Str(ItemInfo.pt.x,StrEnd(PFinal));
StrCat(PFinal,',');
Str(ItemInfo.pt.y,StrEnd(PFinal));
StrCat(PFinal,',');
Str(ItemInfo.iIcon,StrEnd(PFinal));
StrCat(PFinal,',');
Str(GetProgramHotKey(I),StrEnd(PFinal));
StrCat(PFinal,',');
Str(Byte(GetProgramMinFlag(I)),StrEnd(PFinal));
StrCat(PFinal,^M^J);
End;
PFinal:=StrNew(PDDE);
FreeMem(PDDE,(GroupHeader.cItems+1)*1024);
CloseGroup;
GetGroupDDE:=PFinal;
End;
Begin
End.