home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-10-29 | 13.3 KB | 411 lines | [TEXT/CWIE] |
- { Version History: First released without a version number. This is the }
- { second release (STR# Manipulators #2). It fixes a bug in the function }
- { SetIndString wherein I forgot to reset a pointer after resizing the }
- { resource handle. This can result in the pointer no longer pointing in the }
- { proper place within the resource should memory be moved during the }
- { SetHandleSize call. My apologies if this has caused anyone any trouble. }
- { }
- { }
- { ABOUT STRING MANIPULATORS }
- { }
- { The following Pascal routines were written to complement GetIndString. They }
- { allow the user to add, delete or change individual strings in a string list }
- { resource (STR#). A fourth routine returns the number of strings in the list.}
- { }
- { The following routines, DeleteIndString, GetNumStrings, InsertIndString, }
- { and SetIndString, are copyrighted 1995 by David B. Zwiefelhofer. Feel free }
- { to use them in your code without giving credit. If you release source code }
- { incorporating any of these routines please give me credit. }
- { }
- { SetIndString is based on (a rough translation of) a C routine of the same }
- { name that I saw in one of the comp.sys.mac.programmer newsgroups. }
- { Unfortunately, I've lost the original author's name and so I can't credit }
- { him. If you are the original author, please contact me so that I can give }
- { you proper credit. }
- { }
- { No warranty is made as to the fitness of this code for any use whatsoever. }
- { The user assumes full responsibility for the use of this code. }
- { }
- { SetIndString changes an individual string in a string list resource. }
- { GetNumStrings returns the number of strings in a string list resource. }
- { InsertIndString inserts a new string into a string list resource. }
- { DeleteString removes a string from a string list resource. }
- { }
- { Please direct any comments, questions or bug reports to: }
- { subversive@aol.com (preferred) or }
- { davez@mailbag.com. }
-
- unit StringManipulators;
- interface
- uses
- Globals;
-
- function GetNumStrings(resID: integer): integer;
-
- function DeleteIndString(resID, strIndex: integer): OSErr;
-
- function SetIndString(theStr: Str255; resID, strIndex: integer): OSErr;
-
- function InsertIndString(theStr: Str255; resID, strIndex: integer): OSErr;
-
- implementation
-
- {*********************************BlockMoveData**************************************}
-
- procedure BlockMoveData (srcPtr: univ Ptr; destPtr: univ Ptr; byteCount: Size);
- inline
- $201F, $225F, $205F, $A22E;
-
-
-
-
- {*********************************GetNumStrings**************************************}
- { Returns the number of strings in a string list (STR#) resource. The parameters }
- { are: resID is the STR# resource ID. }
- function GetNumStrings(resID: integer): integer;
- var
- theRes: Handle; { handle pointing to STR# resource }
- howMany:integer; { number of strings in STR# resource }
- label
- 100;
- begin
- howMany := 0;
-
- { make sure resource exists }
- theRes := GetResource(kStringListType, resID);
- if (theRes = nil) then
- goto 100;
-
- HLockHi(theRes);
- HNoPurge(theRes);
-
- { get # of strings in STR# }
- BlockMoveData(theRes^, @howMany, sizeof(SInt16));
-
- ReleaseResource(theRes);
- 100:
- GetNumStrings := howMany;
- end;
-
-
-
- {*********************************DeleteIndString**************************************}
- { Deletes an individual string in a string list (STR#) resource. The parameters }
- { are: resID is the STR# resource ID, strIndex is the number of the individual }
- { string to be deleted. }
- function DeleteIndString(resID, strIndex: integer): OSErr;
- var
- theRes: Handle; { handle pointing to STR# resource }
- numStrings, { number of strings in STR# }
- ourString: integer; { counter to index up to strIndex }
- resStr: StringPtr; { string pointer to STR# string to delete }
- oldSize, { size of STR# resource before call }
- newSize: longint; { size of STR# resource after call }
- offset: UInt32; { resource offset to str to delete }
- theErr: OSErr; { error code }
- srcPtr, dstPtr: Ptr; { source and destination pointers and … }
- byteCount:integer; { amount to copy for BlockMoveData call }
- const
- kStringOutOfRange = -100;
- label
- 100;
- begin
- { make sure string exists }
- if strIndex < 1 then
- begin
- theErr := kStringOutOfRange;
- goto 100;
- end;
-
- { make sure resource exists }
- theRes := GetResource(kStringListType, resID);
- if (theRes = nil) then
- begin
- theErr := ResError;
- goto 100;
- end;
-
- HLockHi(theRes);
- HNoPurge(theRes);
-
- { get # of strings in STR# }
-
- BlockMoveData(theRes^, @numStrings, sizeof(SInt16));
- if (strIndex > numStrings) then
- begin
- theErr := kStringOutOfRange;
- goto 100;
- end;
-
- { get a pointer to the string to delete }
-
- offset := sizeof(SInt16);
- resStr := StringPtr(ORD4(theRes^) + sizeof(SInt16)); { pointer to the first string }
- for ourString := 1 to strIndex - 1 do
- begin
- offset := offset + 1 + ORD4(resStr^[0]); { offset is distant from start of theRes to resStr }
- resStr := StringPtr(ORD4(resStr) + 1 + ORD4(resStr^[0]));
- end;
-
-
- { move old data forward }
- oldSize := GetHandleSize(theRes);
-
- newSize := oldSize - ORD4(resStr^[0]) - 1;
-
- srcPtr := Ptr(ORD4(resStr) + LENGTH(resStr^) + 1); { the start of the string following string to delete }
- dstPtr := Ptr(resStr); { the start of the string to delete }
- byteCount := oldSize - offset - ORD4(resStr^[0]) - 1;{ theRes's size less offset to delete string less delete string's size }
-
- BlockMoveData(srcPtr, dstPtr, byteCount);
-
-
- { shrink resource handle to eliminate unused space }
- if newSize < oldSize then
- begin
- HUnlock(theRes);
- SetHandleSize(theRes,newSize);
- if (MemError <> noErr) then
- begin
- theErr := MemError;
- goto 100;
- end;
- HLock(theRes);
- end;
-
- numStrings := numStrings - 1;
- BlockMoveData(@numStrings, theRes^, sizeof(SInt16));
-
- { write resource out }
-
- ChangedResource(theRes);
- WriteResource(theRes);
- HPurge(theRes);
-
- theErr := ResError;
- 100:
- if theRes <> nil then
- ReleaseResource(theRes);
- DeleteIndString := theErr;
- end;
-
-
-
- {*********************************SetIndString**************************************}
- { Replaces an individual string in a string list (STR#) resource. The parameters }
- { are: theStr is the new string, resID is the STR# resource ID, strIndex is the }
- { number of the individual string to be replaced. }
- function SetIndString(theStr: Str255; resID, strIndex: integer): OSErr;
- var
- theRes: Handle; { handle pointing to STR# resource }
- numStrings, { number of strings in STR# }
- ourString: integer; { counter to index up to strIndex }
- resStr: StringPtr; { string pointer to STR# string to replace }
- oldSize, { size of STR# resource before call }
- newSize: longint; { size of STR# resource after call }
- offset: UInt32; { resource offset to str to replace }
- theErr: OSErr; { error code }
- oldStringSize, newStringSize: integer;{ sizes of old and new strings }
- srcPtr, dstPtr: Ptr; { source and destination pointers and … }
- byteCount:integer; { amount to copy for BlockMoveData call }
- const
- kStringOutOfRange = -100;
- label
- 100;
- begin
- { make sure string exists }
- if strIndex < 1 then
- begin
- theErr := kStringOutOfRange;
- goto 100;
- end;
- { make sure resource exists }
- theRes := GetResource(kStringListType, resID);
- if (theRes = nil) then
- begin
- theErr := ResError;
- goto 100;
- end;
-
- HLockHi(theRes);
- HNoPurge(theRes);
-
- { get # of strings in STR# }
-
- BlockMoveData(theRes^, @numStrings, sizeof(SInt16));
- if (strIndex > numStrings) then
- begin
- theErr := kStringOutOfRange;
- goto 100;
- end;
-
- { get a pointer to the string to replace }
-
- offset := sizeof(SInt16);
- resStr := StringPtr(ORD4(theRes^) + sizeof(SInt16)); { pointer to the first string }
- for ourString := 1 to strIndex - 1 do
- begin
- offset := offset + 1 + ORD4(resStr^[0]);
- resStr := StringPtr(ORD4(resStr) + 1 + ORD4(resStr^[0]));
- end;
-
- { grow resource handle to make room for new string }
- oldSize := GetHandleSize(theRes);
- oldStringSize := LENGTH(resStr^) + 1;
- newStringSize := LENGTH(theStr) + 1;
- newSize := oldSize - oldStringSize + newStringSize;
- if newSize > oldSize then
- begin
- HUnlock(theRes);
- SetHandleSize(theRes, newSize);
- if (MemError <> noErr) then
- begin
- theErr := MemError;
- goto 100;
- end;
- HLock(theRes);
- end;
-
- resStr := StringPtr(ORD4(theRes^) + offset);{ forgot to reset resStr after resizing }
- { theRes, (memory may have been moved!) }
- if newSize <> oldSize then
- begin { move old data forward/backward to make room }
- srcPtr := Ptr(ORD4(resStr) + LENGTH(resStr^) + 1); { the start of the string following target string }
- dstPtr := Ptr(ORD4(resStr) + LENGTH(theStr) + 1); { the start of the string following replacement string }
- byteCount := oldSize - offset - ORD4(resStr^[0]) - 1;
-
- BlockMoveData(srcPtr, dstPtr, byteCount);
- end;
-
- { move new data in }
-
- BlockMoveData(@theStr, resStr, LENGTH(theStr) + 1);
-
- { shrink resource handle to eliminate unused space }
- if newSize < oldSize then
- begin
- HUnlock(theRes);
- SetHandleSize(theRes,newSize);
- if (MemError <> noErr) then
- begin
- theErr := MemError;
- goto 100;
- end;
- HLock(theRes);
- end;
-
- { write resource out }
-
- ChangedResource(theRes);
- WriteResource(theRes);
-
- theErr := ResError;
- 100:
- if theRes <> nil then
- ReleaseResource(theRes);
- SetIndString := theErr;
- end;
-
-
-
- {*********************************InsertIndString**************************************}
- { Inserts a new string into a string list (STR#) resource. The parameters are: theStr }
- { is the new string, resID is the STR# resource ID, strIndex is the number of the }
- { string before which the new string is inserted. }
- function InsertIndString(theStr: Str255; resID, strIndex: integer): OSErr;
- var
- theRes: Handle; { handle pointing to STR# resource }
- numStrings, { number of strings in STR# }
- ourString: integer; { counter to index up to strIndex }
- resStr: StringPtr; { string pointer to STR# string to replace }
- oldSize, { size of STR# resource before call }
- newSize: longint; { size of STR# resource after call }
- offset: UInt32; { resource offset to str to replace }
- theErr: OSErr; { error code }
- srcPtr, dstPtr: Ptr; { source and destination pointers and … }
- byteCount:integer; { amount to copy for BlockMoveData call }
- const
- kStringOutOfRange = -100;
- label
- 100;
- begin
- if strIndex < 1 then { strIndex is the number of the string before which }
- begin { we will insert the new string. }
- theErr := kStringOutOfRange;
- goto 100;
- end;
- { make sure resource exists }
- theRes := GetResource(kStringListType, resID);
- if (theRes = nil) then
- begin
- theErr := ResError;
- goto 100;
- end;
-
- HLockHi(theRes);
- HNoPurge(theRes);
-
- { get # of strings in STR# }
-
- BlockMoveData(theRes^, @numStrings, sizeof(SInt16));
- if (strIndex > numStrings) then
- strIndex := numStrings + 1;
-
- oldSize := GetHandleSize(theRes);
- newSize := oldSize + ORD4(theStr[0]) + 1;
-
- { grow resource handle to make room for new string }
-
- HUnlock(theRes);
- SetHandleSize(theRes, newSize);
- if (MemError <> noErr) then
- begin
- theErr := MemError;
- goto 100;
- end;
- HLock(theRes);
-
- { get a pointer to the string to insert before }
-
- if strIndex <= numStrings then
- begin
- offset := sizeof(SInt16);
- resStr := StringPtr(ORD4(theRes^) + sizeof(SInt16)); { pointer to the first string }
- for ourString := 1 to strIndex - 1 do
- begin
- offset := offset + 1 + ORD4(resStr^[0]);
- resStr := StringPtr(ORD4(resStr) + 1 + ORD4(resStr^[0]));
- end;
- { move old data backward to make room }
-
- srcPtr := Ptr(resStr); { the string to insert before is moved }
- dstPtr := Ptr(ORD4(resStr) + LENGTH(theStr) + 1); { back to accommodate the new string }
- byteCount := oldSize - offset;
-
- BlockMoveData(srcPtr, dstPtr, byteCount);
-
- { move new data in }
-
- BlockMoveData(@theStr, resStr, LENGTH(theStr) + 1);
- end
- else { the string to insert before doesn't exist so }
- begin { we add the string to the end of the resource }
- BlockMoveData(@theStr, Ptr(ORD4(theRes^) + oldSize), LENGTH(theStr) + 1);
- end;
-
- numStrings := numStrings + 1;
- BlockMoveData(@numStrings, theRes^, sizeof(SInt16));
-
- { write resource out }
-
- ChangedResource(theRes);
- WriteResource(theRes);
-
- theErr := ResError;
- 100:
- if theRes <> nil then
- ReleaseResource(theRes);
- InsertIndString := theErr;
- end;
-
- end.