Previous code allowed to execute partial matches (this is the reason you will always select "Optic Pro S28 Pro", that partially matches with "Optic Pro S28").
To avoid to break old code, I think it is better to execute an exact match first, then a partial patch.
This is the changed code (for 4.x version):
function TIETwainParams.SelectSourceByName(const sn: AnsiString): boolean;
var
q: integer;
bestMatch: integer;
bestMatchLen: integer;
toFind, current: AnsiString;
minLen: integer;
begin
result := false;
FillSourceListData;
bestMatch := -1;
toFind := IEUpperCase(sn);
// search for exact match
for q := 0 to fSourceListData.Count - 1 do
if (IEUpperCase(IETrim(AnsiString(pTW_IDENTITY(fSourceListData[q])^.ProductName))) = toFind) then
begin
bestMatch := q;
break;
end;
if bestMatch = -1 then
begin
// partial match
bestMatchLen := 0;
for q := 0 to fSourceListData.Count - 1 do
begin
current := IETrim(AnsiString(pTW_IDENTITY(fSourceListData[q])^.ProductName));
minLen := imin(length(current), length(toFind));
if (IEUpperCase(IECopy(current, 1, minLen)) = IECopy(toFind, 1, minLen)) and (minLen > bestMatchLen) then
begin
bestMatch := q;
bestMatchLen := minLen;
end;
end;
end;
if bestMatch <> -1 then
begin
if fSelectedSource <> bestMatch then
SetSelectedSource(bestMatch);
result := true;
end;
// Make Twain the API for subsequent calls to Acquire
{$IFDEF IEINCLUDEMULTIVIEW}
If Result and (fOwner is TImageEnMIO) then
(fOwner as TImageEnMIO).AcquireParams.fSelectedSourceAPI := ieaTwain
else
{$ENDIF}
If Result and (fOwner is TImageEnIO) then
(fOwner as TImageEnIO).AcquireParams.fSelectedSourceAPI := ieaTwain;
end;
This is for 3.x versions (not tested!):
function TIETwainParams.SelectSourceByName(const sn: AnsiString): boolean;
var
q: integer;
bestMatch: integer;
bestMatchLen: integer;
toFind, current: AnsiString;
minLen: integer;
begin
result := false;
FillSourceListData;
bestMatch := -1;
toFind := IEUpperCase(sn);
// search for exact match
for q := 0 to fSourceListData.Count - 1 do
if (IEUpperCase(IETrim(AnsiString(pTW_IDENTITY(fSourceListData[q])^.ProductName))) = toFind) then
begin
bestMatch := q;
break;
end;
if bestMatch = -1 then
begin
// partial match
bestMatchLen := 0;
for q := 0 to fSourceListData.Count - 1 do
begin
current := IETrim(AnsiString(pTW_IDENTITY(fSourceListData[q])^.ProductName));
minLen := imin(length(current), length(toFind));
if (IEUpperCase(IECopy(current, 1, minLen)) = IECopy(toFind, 1, minLen)) and (minLen > bestMatchLen) then
begin
bestMatch := q;
bestMatchLen := minLen;
end;
end;
end;
if bestMatch <> -1 then
begin
if fSelectedSource <> bestMatch then
SetSelectedSource(bestMatch);
result := true;
end;
end;