TMGPAT1  ;TMG/kst/Patching tools ;09/17/08
         ;;1.0;TMG-LIB;**1**;09/17/08
 ;
 ;"Kevin Toppenberg MD
 ;"GNU General Public License (GPL) applies
 ;"9/17/08

 ;"=======================================================================
 ;" API -- Public Functions.
 ;"=======================================================================
 ;"DONEXT -- Ask for package, and install next appropriate patch
 ;"DONEXTPJ -- do next patch within the same project
 ;"FIXMISEQ -- allow fixing a missing patch, based on sequence order
 ;"FIXMISPT -- allow fixing a missing patch, based on patch number
 ;"DONEXTPK(PckInit,Ver)-- a common entry point
 ;"GO(Option,Info,Msg) -- Entry point to allow automatic loading and installation of a patch.
 ;"LOAD -- Entry point to allow manual loading of a patch (like old way, but using new code)

 ;"=======================================================================
 ;"Private Functions
 ;"=======================================================================
 ;"Logo
 ;"FixMissing(Mode) allow fixing a missing patch, even if it is out of sequence order
 ;"FixMisInit(PckInit,Ver,Mode) -- Based on PckInit, and Version, allow fixing a missing patch, even if it is out of sequence order
 ;"DoFixMissing(IENS,Mode) -- fix a missing patch, even if it is out of sequence order
 ;"DoIENS(NextIENS,NextPatch,PckDirFName) -- install patch, given IENS to it's entry in 22709.11
 ;"GetPckVer(PckInit,Ver) -- query user for package, and desired version
 ;"GetLastPackage(PckInit,Ver) -- for given package initials, return the last patch applied
 ;"GetPVIEN(PckInit,Ver,IEN9d4,IEN9d49) -- convert PckInit and Ver into IEN's for file 9.4 ad 9.49
 ;"GetLastInst(PckInit,Ver,InstIEN) -- for given package initials, return the last patch applied in INSTALL file
 ;"GetVers(PckInit,VerArray) --for given package initials, return possible versions
 ;"PickFile(pArray) -- Pick a filename from a list, in a menu

 ;"=======================================================================

Logo    write !!,"===================",!
        write "TMG Patcher Helper",!
        write "===================",!
        quit

DONEXT
        ;"Purpose: Ask for package, and install next appropriate patch
        do Logo
        new PckInit,Ver
        do GetPckVer(.PckInit,.Ver)
        if Ver="^" goto DNDone
        do DONEXTPK(PckInit,Ver)
        goto DONEXT
DNDone
        quit

DONEXTPJ
        ;"Purpose: to do next patch within the same project
        do Logo
        new PckInit,Ver
        new s set s=$get(^TMG("KIDS","PROJECT"))
        if s'="" do
        . set PckInit=$piece(s,"^",1)
        . set Ver=$piece(s,"^",2)
        else  do
        . do GetPckVer(.PckInit,.Ver)
        . set s=PckInit_"^"_Ver
        . set ^TMG("KIDS","PROJECT")=s
        if Ver="^" goto DNDone
        do DONEXTPK(PckInit,Ver)
DNPJDone
        quit


FIXMISEQ
        ;"Purpose: to allow fixing a missing patch, based on sequence order
        do FixMissing(1)
        quit


FIXMISPT
        ;"Purpose: to allow fixing a missing patch, based on patch number
        do FixMissing(2)
        quit


FixMissing(Mode)
        ;"Purpose: to allow fixing a missing patch, even if it is out of sequence order
        ;"         This will prepare, then call DoFixMissing()
        ;"Input: Mode -- 1: search by SEQ#, 2: search by Patch#
        do Logo
        write "Fix missing patches, regardless of order",!
        new PckInit,Ver
        do GetPckVer(.PckInit,.Ver) goto:(Ver="^") FMIDone
        ;"set IENS=$$AskIENS^TMGDBAPI(22709.01) goto:(IENS="") FMIDone
        do FixMisInit(.PckInit,.Ver,.Mode)
FMDone  quit


FixMisInit(PckInit,Ver,Mode)
        ;"Purpose: Based on PckInit, and Version, allow fixing a missing patch, even if it is out of sequence order
        ;"         This will prepare, then call DoFixMissing()
        ;"Input: Mode -- 1: search by SEQ#, 2: search by Patch#
        set PckInit=$get(PckInit) goto:(PckInit="") FMIDone
        set Ver=$get(Ver) goto:(Ver="") FMIDone
        new IENS set IENS=$$GetIENS2^TMGPAT2(PckInit_"*"_Ver) goto:(IENS="") FMIDone
        do DoFixMissing(IENS,.Mode)
FMIDone quit


DoFixMissing(IENS,Mode)
        ;"Purpose: fix a missing patch, even if it is out of sequence order
        ;"Input: IENS -- should be IENS from file 27709.01
        ;"              i.e. 'IEN22709d01,IEN22709,'
        ;"       Mode -- 1: search by SEQ#, 2: search by Patch#

        new PckInit,Ver,Y,PatchName,Msg,PckDirFName
        new IEN1 set IEN1=+$piece(IENS,",",2) goto:(IEN1'>0) FMSDone
        new IEN2 set IEN2=+$piece(IENS,",",1) goto:(IEN2'>0) FMSDone
        new IEN9d4 set IEN9d4=$piece($get(^TMG(22709,IEN1,0)),"^",1) goto:(IEN9d4'>0) FMSDone
        set PckInit=$piece($get(^DIC(9.4,IEN9d4,0)),"^",2)
        set Ver=$piece($get(^TMG(22709,IEN1,1,IEN2,0)),"^",1) goto:(Ver="") FMSDone
        new saveIENS set saveIENS=IENS
        set Mode=+$get(Mode,1)

        do MAKFRESH^TMGPAT2(PckInit,.Msg,.PckDirFName)
FMLoop  new SrchNum,DIR
        set DIR(0)="N^1:9999:0"
        if Mode=1 set DIR("A")="Enter missing patch SEQUENCE NUMBER"
        else  set DIR("A")="Enter missing PATCH NUMBER"
        do ^DIR write !
        if $get(DIRUT) goto FMSDone
        set SrchNum=+Y

        ;"Search for specified Patch/Seq #
        new found set found=0
        new IEN3 set IEN3=0
        new PatchNum set PatchNum=0
        new SeqNum set SeqNum=0
        for  set IEN3=$order(^TMG(22709,IEN1,1,IEN2,1,IEN3)) quit:(IEN3'>0)!found  do
        . set PatchNum=$piece($get(^TMG(22709,IEN1,1,IEN2,1,IEN3,0)),"^",1)
        . set SeqNum=$piece($get(^TMG(22709,IEN1,1,IEN2,1,IEN3,0)),"^",2)
        . if (Mode=1),(SeqNum=SrchNum) set found=IEN3
        . else  if (Mode=2),(PatchNum=SrchNum) set found=IEN3
        . if found do
        . . set IENS=IEN3_","_IENS
        . . set PatchName=PckInit_"*"_Ver_"*"_PatchNum_" SEQ #"_SeqNum

        if found=0 do  goto FMSDone
        . write "Sorry.  Can't find that Patch/Seq Number in downloaded info from ftp.va.gov",!

        write "Found: ",PatchName," on ftp.va.gov server.",!

        ;"Now see if already installed
        new DIC,X,Y,IEN9d49
        ;"set IEN9d49=+$order(^DIC(9.4,IEN9d4,22,"B",Ver,""))
        set DIC="^DIC(9.4,"_IEN9d4_",22,"
        set DIC(0)="M"
        set X=Ver
        do ^DIC
        set IEN9d49=+Y
        if IEN9d49'>0 do  goto FMSDone
        . write "?? Can't find that version in the PACKAGE file",!

        set found=0
        new i set i=""
        for  set i=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH","B",i)) quit:(i="")!found  do
        . new onePatchNum set onePatchNum=$piece(i," ",1)
        . ;"write onePatchNum,!
        . if onePatchNum=PatchNum set found=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH","B",i,""))

        if found do  goto FMSMore
        . new newIENS set newIENS=found_","_IEN9d49_","_IEN9d4
        . write "Sorry, that patch is already installed.  IENS='",newIENS,"'",!
        . do ForceP2^TMGPAT2(PckInit,Ver,PatchNum,SeqNum)


        new % set %=1
        write "Do you want to work on this patch now (out of sequence order)" do YN^DICN write !
        if %'=1 goto FMSDone

        if $$DoIENS(IENS,PatchName,.PckDirFName)  ;"actually process patch

FMSMore set %=1
        write "Fix others in this same Package-Version" do YN^DICN write !
        if %=1 do  goto FMLoop
        . set IENS=saveIENS

FMSDone
        quit


DONEXTPK(PckInit,Ver)
        ;"Purpose: a common entry point
        ;"Input: PckInit -- package initials
        ;"       Ver -- version e.g. '22.0'
        ;"Result: None

        new LastPck,NextIENS,NextPatch,LastInst,PckDirFName
        new Info,Msg,Option,result,restart,InstIEN,abort,chgVer

        set (abort,restart,chgVer)=0
        do MAKFRESH^TMGPAT2(PckInit,.Msg,.PckDirFName)
DNP1    set LastPck=$$GetLastPackage(PckInit,Ver)
        if LastPck="" do  goto AllDone
        . write "Sorry, can't find any installed packges in that version.",!
        set LastInst=$$GetLastInst(PckInit,Ver,.InstIEN)
        write "The last patch installed into PACKAGE file was: ",?50,LastPck,!
        if LastInst="" goto DNP2
        write "The last patch loaded into the INSTALL file was: ",?50,LastInst," (FYI)",!
        if +$piece(LastPck,"SEQ #",2)<+$piece(LastInst,"SEQ #",2) do  goto:(restart) AllDone
        . new % set %=2
        . write !,"Undelete entry in INSTALL FILE" do YN^DICN write !
        . if %=1 do  quit
        . . do EN1^TMGXPDIU(InstIEN)
        . . set restart=1
        . set %=1
        . write "Try to continue with existing files" do YN^DICN write !
        . if %'=1 set restart=1 quit
        if restart goto AllDone
DNP2    set NextIENS=$$GetNextIENS^TMGPAT2(LastPck,.NextPatch)
        new pendingCt set pendingCt=$$Rpt1Avail^TMGPAT3(LastPck)
        if pendingCt>0 write "Number of pending patches for this package:",?50,pendingCt,!
        else  do  goto:(chgVer) DNP1
        . if $$RptAvail^TMGPAT3(PckInit)=0 set chgVer=0 quit
        . do AskVer(PckInit,.Ver)
        . set chgVer=1

        if $$DoIENS(NextIENS,NextPatch,.PckDirFName)=0 goto AllDone

More    set %=1
        write "Do more patch installations in this package" do YN^DICN write !!
        if %=1 goto DNP1
AllDone
        quit

DoIENS(NextIENS,NextPatch,PckDirFName)
        ;"Purpose: install patch, given IENS to it's entry in 22709.11
        ;"Input: NextIENS -- IENS for entry in 22709.11
        ;"       NextPatch -- Patch Name of patch to be applied.
        ;"Results: 1 if OK, 0 if problem.

        new abort set abort=0
        if NextPatch'="" do
        . write "Next patch to install is: ",?50,NextPatch,!
        else  do  goto DNPDone
        . write "No more patches available for this package.",!
        . set abort=1
        . quit;  ;"//kt fix below later...
        . write "View list of all patches for this package on ftp server"
        . set %=2
        . do YN^DICN write !
        . if %=1 if $$EditHFSFile^TMGKERNL(PckDirFName)
        . if %=-1 set restart=1 quit
        new Option set Option("VERBOSE")=1
        set result=$$EnsureLocal^TMGPAT2(NextIENS,.Info,.Msg,.Option)
        if result=0 do  goto DNPDone
        . do AddMsg^TMGPAT2("Unable to find patch on local file system.",1,Msg)
        . if $$ShowMsg^TMGPAT2(.Msg)

        new % set %=1
        if $get(Info("KID FILE"))'="" do PAnalyze^TMGPAT4(.Info,.Option)
        if $get(Info("TEXT FILE"))'="" do  goto:(abort=1) DNPDone
        . do Analyze^TMGPAT4(.Info,.Option)
        . new tempMsg
        . do ShowAnalysis^TMGPAT4(.Info,.tempMsg)
        . if $$ShowMsg^TMGPAT2(.tempMsg,1)
        . kill tempMsg
        . new FilePathName set FilePathName=$get(Info("PATH"))_$get(Info("TEXT FILE"))
        . set %=1
        . write "View INFO FILE for patch" do YN^DICN write !
        . if %=-1 quit
        . if %=1 if $$EditHFSFile^TMGKERNL(FilePathName)
        . if $get(Info("KID FILE"))="" do
        . . new FName set FName=""
        . . if $get(Info("MULTI-PATCH","FILENAME"))'="" do
        . . . set Info("KID FILE")=Info("MULTI-PATCH","FILENAME")
        . . else  if ($$ListCt^TMGMISC($name(Info("PATCH CATEGORY")))=1)&($data(Info("PATCH CATEGORY","Informational"))) quit
        . . else  if $data(Info("MISC KID FILES")) do
        . . . write !,"No typical KIDS file found for this patch.  However, one or more filenames",!
        . . . write "were scraped from the TEXT file.  Having read the TEXT file, see if one of these",!
        . . . write "names is correct.",!!
        . . . set Info("KID FILE")=$$PickFile($name(Info("MISC KID FILES")))
        . . if $get(Info("KID FILE"))'="" set Info("TEXT ONLY")=0
        . . set FName=$get(Info("KID FILE"))
        . . if FName="" quit
        . . set %=2
        . . write !,"Attempt to download ",FName," from ftp.va.gov?",!
        . . write "NOTE: if this file doesn't exist on the server, then the process will HANG.",!
        . . write "If this happens, then use a utility to abort process #",$J," from OS prompt.",!
        . . write "Download '",FName,"'" do YN^DICN write !
        . . if %'=1 quit
        . . if $$DownloadPatch^TMGPAT2(FName,"ftp://",.Option,.tempMsg,.Info)=0
        . . . write "ERROR: Can't download file: ",Info("KID FILE")," from ftp server.",!
        . . . do PressToCont^TMGUSRIF
        . . . ;"handle error here...
        . . if $$ShowMsg^TMGPAT2(.tempMsg,1)
        if %=-1 goto DNPDone

        if $data(Info("STILL NEEDED")) do  goto:(abort=1) DNPDone
        . new pArray set pArray=$name(Info("STILL NEEDED"))
        . do StoreMissing^TMGPAT3(PckInit,pArray)
        . write "It seems that the system is not ready for this patch.",!
        . write "(However, sometimes this can be ignored and one can proceed anyway.)",!
        . set %=1
        . write "Quit this patch and try another" do YN^DICN write !
        . if %'=2 set abort=1

        if $get(Info("TEXT ONLY"))=1 do  goto DNPDone
        . write "This 'patch' doesn't have a corresponding KID file.",!
        . write "Perhaps it was informational only.  I'm not smart enough to figure that out.",!
        . write "If you didn't read the INFO FILE, then answer NO, and loop back and read it.",!
        . set %=2
        . write "Ready to consider the patch 'installed'" do YN^DICN write !
        . if %'=1 quit
        . if $$MakePatchEntry^TMGPAT2(NextPatch,.Msg)

        if $get(Info("KID FILE"))="" do  goto DNPDone
        . write "?? No name for KID file ??",!

        set %=1
        write "Ready to load patch "_Info("KID FILE")_" into system" do YN^DICN write !
        if %'=1 set %=-1 goto DNPDone
        new result set result=$$GO(.Option,.Info,.Msg)

        quit result


GO(Option,Info,Msg)
        ;"Purpose: Entry point to allow automatic loading and installation of a patch.
        ;"Input: Option -- PASS BY REFERENCE.  Can be an empty array.
        ;"       Info -- PASS BY REFERENCE.
        ;"       Msg -- PASS BY REFERNCE.
        ;"Results: 1 if OK, 0 if problem.

        new abort set abort=0
        set Option("HFSNAME")=$get(Info("PATH"))_Info("KID FILE")
        set Option("FORCE CONT LOAD")=1
        set Option("DO ENV CHECK")=1
        do EN1^TMGXPDIL(.Option,.Msg)
        new errorFound set errorFound=$$ShowMsg^TMGPAT2(.Msg,1)
        if errorFound goto DNP3
        new InstallName set InstallName=$get(Option("INSTALL NAME"))
        if InstallName="" do  goto DNPDone
        . write "No installation name found.  Aborting.",!
        . set abort=1
        new % set %=1
        write "Proceed with installation" do YN^DICN write !
        kill Msg
        new Option ;"... FINISH..., add presets to avoid user interactivity later...
        set Option("Want to DISABLE Scheduled Options, Menu Options, and Protocols","DEFAULT")="NO"
        set Option("Want KIDS to INHIBIT LOGONs during the install","DEFAULT")="NO"
        set Option("Want KIDS to Rebuild Menu Trees Upon Completion of Install","DEFAULT")="NO"
        if %=1 do EN^TMGXPDI(InstallName,.Option,.Msg)
        if $$ShowMsg^TMGPAT2(.Msg,1)
DNP3
        new tempNull
        if $data(PckInit) do
        . do StoreMissing^TMGPAT3(PckInit,"tempNull") ;"clear out pending patches...
        else  goto DNPDone

        set %=1
        write "Clean up local files for this patch" do YN^DICN write !
        if %=-1 goto DNPDone
        if %=1 do
        . new path set path=$get(Info("PATH"))
        . new fileName set fileName=$get(Info("KID FILE"))
        . if fileName'="" if $$DelFile^TMGIOUTL(path_fileName)
        . set fileName=$get(Info("TEXT FILE"))
        . if fileName'="" if $$DelFile^TMGIOUTL(path_fileName)

DNPDone quit (abort=0)


LOAD
        ;"Purpose: Entry point to allow manual loading of a patch (like old way, but using new code)
        do Logo^TMGPAT1 write !
        new FPName,FPath,FName,Msg,Option,Info
        set FPName=$$GetFName^TMGIOUTL("Select Patch to Load",,,,.FPath,.FName)
        if (FPName'="")&(FPName'="^") do
        . set Info("PATH")=FPath,Info("KID FILE")=FName
        . new result set result=$$GO(.Option,.Info,.Msg)
        quit


GetPckVer(PckInit,Ver)
        ;"Purpose: query user for package, and desired version
        ;"Input: PckInit - PASS BY REFERENCE.  An OUT PARAMETER. The package initials, e.g. 'DI' in the case of filemant
        ;"       Ver -- PASS BY REFERENCE.  An OUT PARAMETER.  The version of the package to match.
        ;"results: none;  (if user aborted, Ver="^")

        set Ver="^"
        new DIC,X,Y
        set DIC=9.4,DIC(0)="MAEQ"  ;"ask for package name
        do ^DIC write !
        if +Y'>0 goto GPVDone
        new Package set Package=$piece(Y,"^",2)
        set PckInit=$piece($get(^DIC(9.4,+Y,0)),"^",2)
        if PckInit="" do  goto GPVDone
        . write "Error.  Unable to obtain package prefix.",!
        do AskVer(PckInit,.Ver)

GPVDone quit

AskVer(PckInit,Ver,Package)
        ;"Purpose: query user for desired version from specified package
        ;"Input: PckInit - The package initials, e.g. 'DI' in the case of filemant
        ;"       Ver -- PASS BY REFERENCE.  An OUT PARAMETER.  The version of the package to match.
        ;"       Package -- OPTIONAL.  Name of Package.  Default is same as PckInit
        ;"results: none;  (if user aborted, Ver="^")

        new VerArray
        do GetVers(PckInit,.VerArray)
        if $data(VerArray)=0 do  goto AVrDone
        . write "Error. No version number available.",!
        if $get(Package)="" set Package=PckInit
        ;
        new Menu,i,Usr
        set Menu(0)="Select Version of "_Package
        set Ver="",i=0
        for  set Ver=$order(VerArray(Ver)) quit:(Ver="")  do
        . set i=i+1
        . new tempPatch set tempPatch=PckInit_"*"_Ver_"*1"
        . new count set count=+$$Rpt1Avail^TMGPAT3(tempPatch)
        . set Menu(i)="Version "_Ver_" ("_count_" patches pending)"_$C(9)_Ver
        if i=1 set Ver=$order(VerArray(""))  ;"must be only one option, so skip menu
        else  do
        . set Ver=$$Menu^TMGUSRIF(.Menu,"^")
        ;
AVrDone quit


GetPVIEN(PckInit,Ver,IEN9d4,IEN9d49)
        ;"Purpose: to convert PckInit and Ver into IEN's for file 9.4 ad 9.49
        ;"Input: PckInit - .  The package initials, e.g. 'DI' in the case of filemant
        ;"       Ver -- The version of the package to match.
        ;"       IEN9d4 - PASS BY REFERENCE.  The IEN in 9.4 to return
        ;"       IEN9d49 -- PASS BY REFERENCE.  The IEN in 9.49 to return
        ;"result: 1 if OK, 0 if not found.

        new result set result=0
        ;
        set IEN9d4=+$order(^DIC(9.4,"C",PckInit,""))
        if IEN9d4'>0 goto GPVIDne
        new DIC,X,Y
        set DIC="^DIC(9.4,"_IEN9d4_",22,"
        set DIC(0)="M"
        set X=Ver
        do ^DIC
        set IEN9d49=+Y
        if IEN9d49'>0 goto GPVIDne
        set result=1
        ;
GPVIDne quit result


GetLastPackage(PckInit,Ver)
        ;"Purpose: for given package initials, return the last patch applied
        ;"         This searches the PACKAGE file
        ;"Input: PckInit - the package initials, e.g. 'DI' in the case of filemant
        ;"       Ver -- the version of the package to match.
        ;"Results: returns e.g. 'DI*22.0*140 SEQ# 123'
        ;"         or "" if problem or not found.

        new result set result=""
        set Ver=$get(Ver)
        set PckInit=$get(PckInit)
        if (PckInit="")!(Ver="") goto GLPDone
        new IEN9d4,IEN9d49
        set IEN9d4=+$order(^DIC(9.4,"C",PckInit,""))
        if IEN9d4'>0 goto GLPDone
        set IEN9d49=+$order(^DIC(9.4,IEN9d4,22,"B",Ver,""))
        if IEN9d49'>0 goto GLPDone

        new i,array
        set i=""
        for  set i=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH","B",i)) quit:(i="")  do
        . new patchNum set patchNum=$piece(i," ",1)
        . new seqNum set seqNum=$piece(i,"SEQ #",2)
        . new tempName set tempName=i
        . if seqNum="" do
        . . set tempName=PckInit_"*"_Ver_"*"_patchNum
        . . set tempName=$$GetSeq^TMGPAT4(tempName)
        . . set seqNum=$piece(tempName,"SEQ #",2)
        . . if seqNum="" quit
        . . new IEN9d4901 set IEN9d4901=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH","B",i,""))
        . . ;"write "The PACKAGE file entry for patch "_PckInit_"*"_Ver_"*"_patchNum_" doesn't have a SEQ #",!
        . . ;"write "By comparing this to patch files available on ftp.va.gov network site, it",!
        . . ;"write "appears that this patch should be SEQ #",tempName,!
        . . ;"new % set %=1
        . . ;"write "Shall I correct this in the PACKAGE file" do YN^DICN write !
        . . ;"if %'=1 quit
        . . new TMGFDA,TMGMSG
        . . set TMGFDA(9.4901,IEN9d4901_","_IEN9d49_","_IEN9d4_",",.01)=patchNum_" SEQ #"_seqNum
        . . do FILE^DIE("K","TMGFDA","TMGMSG")
        . . ;"do ShowIfDIERR^TMGDEBUG(.TMGMSG)
        . ;"if seqNum is still "" at this point, it won't find the patch, could be bug...
        . set seqNum=$$RJ^XLFSTR(seqNum,6,"0")
        . if tempName["*" set tempName=$piece(tempName,"*",3)
        . set array(seqNum)=tempName

        set i=$order(array(""),-1)
        if i'="" set result=PckInit_"*"_Ver_"*"_$get(array(i))
        else  set result=PckInit_"*"_Ver_"*0 SEQ #0"
        ;"else  set result=$piece($get(^DIC(9.4,IEN9d4,0)),"^",1)_" SEQ #0"

GLPDone
        quit result

GetLastInst(PckInit,Ver,InstIEN)
        ;"Purpose: for given package initials, return the last patch applied
        ;"         This searches the INSTALL file
        ;"Input: PckInit - the package initials, e.g. 'DI' in the case of filemant
        ;"       Ver -- the version of the package to match.
        ;"       InstIEN -- Optional.  Pass by Reference, an OUT PARAMETER.
        ;"Results: returns last patch + 'SEQ# 123' (123 is example)
        ;"         or "" if problem or not found.

        new result set result=""
        new array
        set Ver=$get(Ver)
        new i set i=$get(PckInit)
        if (i="")!(Ver="") goto GLIDone
        new done set done=0
        for  set i=$order(^XPD(9.7,"B",i)) quit:(i="")!done  do
        . if $piece(i,"*",1)'=PckInit set done=1 quit
        . if $piece(i,"*",2)'=Ver quit
        . new patch set patch=$piece(i,"*",3)
        . set patch=$$RJ^XLFSTR(patch,6,"0")
        . new IEN set IEN=$order(^XPD(9.7,"B",i,""))
        . if IEN=0 quit
        . new seq set seq=$$GET1^DIQ(9.7,IEN_",",42001)
        . if seq="" quit
        . ;"write "SEQ #"_seq_"  "_i,!
        . set array(seq)=i_" SEQ #"_seq_"^"_IEN

        set i=$order(array(""),-1)
        set result=$get(array(i))
        set InstIEN=$piece(result,"^",2)
        set result=$piece(result,"^",1)

        if result'="" do
        . new PatIEN set PatIEN=+$order(^XPD(9.7,"B",result,""))
        . if PatIEN=0 quit
        . new Seq set Seq=$$GET1^DIQ(9.7,PatIEN_",",42001)
        . if Seq="" quit
        . set result=result_" SEQ #"_Seq

GLIDone
        quit result



GetVers(PckInit,VerArray)
        ;"Purpose: for given package initials, return possible versions
        ;"Input: PckInit - the package initials, e.g. 'DI' in the case of filemant
        ;"       VerArray -- PASS BY REFERENCE -- an OUT PARAMETER.  Format
        ;"              VerArray("22")=""
        ;"              VerArray("23")=""
        ;"Results: none

        new ver
        kill VerArray
        if $get(PckInit)="" goto GVDone
        new done set done=0
        new ien9d4 set ien9d4=+$order(^DIC(9.4,"C",PckInit,"")) goto:(ien9d4'>0) GVDone
        set ver=""
        for  set ver=$order(^DIC(9.4,ien9d4,22,"B",ver)) quit:(ver="")!done  do
        . if ver'="" set VerArray(ver)=""

GVDone  quit

        ;"Discard below later ============================================
        for  set i=$order(^XPD(9.7,"B",i)) quit:(i="")!done  do
        . if i["*" do
        . . if $piece(i,"*",1)'=PckInit set done=1 quit
        . . set ver=$piece(i,"*",2)
        . else  do
        . . new ien set ien=+$order(^XPD(9.7,"B",i,""))
        . . write i,!
        . . write "From the above name, please enter version number"
        . . new DIR set DIR(0)="N^0:999:2" do ^DIR write !
        . . if $data(DIRUT) set ver="" quit
        . . set ver=X  ;"why doesn't Y return decimals???
        . . set done=1
        . if ver'="" set VerArray(ver)=""
        ;"Discard above later ============================================


PickFile(pArray)
        ;"Purpose: Pick a filename from a list, in a menu
        ;"Input: pArray -- PASS BY NAME.  format:
        ;"        @pArray@(name)=""
        ;"        @pArray@(name)=""
        ;"Result: the chosen name, or "" if problem.

        new menu set menu(0)="Select IF one of the following files is the patch file."
        new count set count=1
        new name set name=""
        for  set name=$order(@pArray@(name)) quit:(name="")  do
        . set menu(count)=name_$C(9)_name
        . set count=count+1
        set menu(count)="(None of these / Cancel)"_$C(9)_"@"
        set count=count+1

        set result=$$Menu^TMGUSRIF(.menu)
        if "@^"[result set result=""
        quit result