CIAUDDR ;MSC/IND/DKM - FileMan RPC Extensions ;04-May-2006 08:19;DKM
;;1.2;CIA UTILITIES;;Mar 20, 2007
;;Copyright 2000-2006, Medsphere Systems Corporation
;=================================================================
; RPC: Retrieve DD information about a file.
; FNUM = File # or name
; FLDS = Semi-colon delimited field list (optional)
; IENS = IENS (for subfile entries)
; FLGS = Control flags:
; D = Fix duplicate field names
; M = Retrieve multiples
; Return data:
; DATA(0) = -1^Error text or
; = File #^File name^Rec count^Field count^Readonly^Parent File
; DATA(n) = Field #^Field name^Datatype^Size^Required^Readonly^Help lines^Xref^Calculated
; DATA(n,0) = Supplemental data (set mappings)
; DATA(n,1) = Prompt Text
; DATA(n,2) = Help Text
GETDD(DATA,FNUM,FLDS,IENS,FLGS) ;
N X,Y,Z,CNT,N0,FLD,PF,MULT,DUPS
S DATA=$NA(^TMP("CIAUDDR",$J))
K @DATA
S FNUM=$G(FNUM),FLDS=$G(FLDS),FLGS=$G(FLGS),MULT=FLGS["M",DUPS=FLGS["D"
I $L(FNUM),FNUM'=+FNUM D
.S FNUM=$O(^DIC("B",FNUM,0))
.I FNUM,$O(^(FNUM)) S FNUM=""
S X=$$ROOT^DILFD(FNUM,$G(IENS),1),PF=$G(^DD(+FNUM,0,"UP"))
S:$L(X) X=$G(@X@(0))
S:PF $P(X,U)=$P($G(^DD(+FNUM,0)),U)
I '$L(X) D SETERR("Table not found") Q
S N0=FNUM_U_$P(X,U)_U_$P(X,U,4),CNT=0
F X=1:1:$L(FLDS,";") D Q:'X
.S FLD=$P(FLDS,";",X)
.Q:'$L(FLD)
.S:FLD="*" FLD="0-9999999999999999"
.I $TR(FLD,".")?1.N1"-"1.N D
..S Z=+$P(FLD,"-"),Y=+$P(FLD,"-",2)
..S:Z<0 Z=0
..I Z=0 S:'$$GETFL(0,0) X=0
..I Z>0,$D(^DD(FNUM,Z,0)) S:'$$GETFL(Z,MULT) X=0
..F Q:'X S Z=$O(^DD(FNUM,Z)) Q:'Z Q:Z>Y S:'$$GETFL(Z,MULT) X=0
.E I '$$GETFL(FLD,1) S X=0
S:X @DATA@(0)=N0_U_CNT_U_($P($G(^DD(FNUM,0,"DI")),U,2)["Y")_U_PF
Q
; Setup type info for field
; FLDX = Field # or name
; MULT = Allow multiples
; Note: Datatype (TP) maps to TFMFieldType enum:
; 0 = unknown, 1 = free text, 2 = numeric, 3 = boolean,
; 4 = date/time, 5 = wp, 6 = pointer, 7 = set, 8 = subfile
GETFL(FLDX,MULT) ;
N X,Z,LN,TP,HC,DD,FLD,MLT,NAM
S FLD=$$FLDNUM(FNUM,FLDX),MLT=0
S DD=$S('$L(FLD):"",FLD:$G(^DD(FNUM,FLD,0)),1:"#^RICJ8,5"),X=$P(DD,U,2)
I '$L(DD) D SETERR("Field not found: "_FLDX) Q 0
I X,$P($G(^DD(X,.01,0)),U,2)'["W" S MLT=1
I 'MULT,MLT Q 1
S (LN,TP,HC,Z)=0,DX="",NAM=$P(DD,U),CNT=CNT+1
I DUPS,$O(^(+$O(^DD(FNUM,"B",NAM,0)))) S NAM=NAM_"("_FLD_")"
I MLT S TP=8,DX=+X
E I X["B" S TP=3
E I X["D" S TP=4,DX=$P($P($P(DD,U,5),"%DT=",2),"""",2)
E I X["F"!(X["K") S TP=1,LN=+$P($P(DD,U,5),"$L(X)>",2) S:'LN LN=30
E I X["J" S TP=2,DX=$P(X,"J",2) S:DX'["," LN=DX,DX="",TP=1
E I X["P"!(X["p") S TP=6,DX=+$P($TR(X,"p","P"),"P",2),LN=$$GETLN(DX)
E I X["S" S TP=7,DX=$P(DD,U,3)
E I X=+X S TP=5
I 'FLD S HC=1,@DATA@(CNT,2,HC)="Internal record number."
E F S Z=$O(^DD(FNUM,FLD,21,Z)) Q:'Z S HC=HC+1,@DATA@(CNT,2,HC)=^(Z,0)
S @DATA@(CNT)=FLD_U_NAM_U_TP_U_LN_U_(X["R")_U_(X["I")_U_HC_U_$$XREF(FNUM,FLD)_U_(X["C")
S @DATA@(CNT,0)=DX,@DATA@(CNT,1)=$G(^DD(FNUM,FLD,3))
Q 1
; Get length of .01 for file
GETLN(FNUM) ;
N DD,X
S DD=$G(^DD(FNUM,.01,0)),X=$P(DD,U,2)
S X=+$S(X["P":$$GETLN(+$E(X,2,99)),X["F":$P($P(DD,U,5),"$L(X)>",2),1:0)
Q $S(X:X,1:30)
SETERR(ERR) ;
K @DATA
S @DATA@(0)="-1^"_ERR
Q
; RPC: CIAUDDR MOVETO
; Move to specified record (returns IEN only)
; FNUM: File #
; IEN : Current IEN
; DIR : 0 = current; 1 = next; 2 = prior
; IENS: Subfile IENS
; SCRN: Screens (optional)
; INDX: Index (optional)
; Returns IEN or <error code>^<error text>
MOVETO(DATA,FNUM,IEN,DIR,IENS,SCRN,INDX) ;
N GBL,IDX,IDF,OK
S GBL=$$ROOT^DILFD(FNUM,$G(IENS),1),DIR=+$G(DIR),INDX=$G(INDX)
S DIR=$S(DIR=1:1,DIR=2:-1,1:0)
S:$L($G(SCRN)) SCRN(-1)=SCRN
I '$L(GBL) S DATA="-4^Table not found" Q
I $L(INDX) D Q:$G(DATA)
.I '$O(^DD(FNUM,0,"IX",INDX,"")) S DATA="-5^Index "_INDX_" not found" Q
.S IDF=$$XREFFLD(FNUM,INDX)
.I 'IDF S DATA="-6^Index "_INDX_" is not a standard index" Q
.S IDX=$S(IEN=-1:"",IEN=-2:$C(255),1:$E($$FLDVAL(FNUM,IDF,IEN,GBL),1,30))
E S IEN=$S(IEN=-1:0,IEN=-2:$O(@GBL@($C(1)),-1)+1,1:+IEN)
F D Q:OK!'IEN
.S IEN=+$$NXTIEN
.;S OK=IEN&(IEN\1=IEN)&$D(@GBL@(IEN,0)),SCRN=""
.S OK=IEN&$D(@GBL@(IEN,0)),SCRN=""
.F Q:'OK S SCRN=$O(SCRN(SCRN)) Q:'$L(SCRN) D
..N Y
..S Y=IEN
..I $D(@GBL@(Y,0))
..X SCRN(SCRN)
..S OK=$T
.I 'OK,'DIR S IEN=0
S DATA=$S(OK:IEN,'DIR:"-3^Record not found",DIR=1:"-2^End of file",1:"-1^Beginning of file")
Q
; Return next IEN
NXTIEN() Q:'DIR IEN
Q:'$L(INDX) $O(@GBL@(IEN),DIR)
N OK
F D Q:OK!'$L(IDX)
.S:IEN'>0 IDX=$O(@GBL@(INDX,IDX),DIR),IEN=""
.S IEN=$S($L(IDX):$O(@GBL@(INDX,IDX,IEN),DIR),1:0)
.;S OK=$S('IEN:0,1:$E($$FLDVAL(FNUM,IDF,IEN,GBL),1,30)=IDX)
.S OK=$S('IEN:0,1:$D(@GBL@(IEN,0)))
Q IEN
; Return field value (internal)
; FIL = File or subfile #
; FLD = Field #
; IEN = Record #
; ROOT = Global root of file or subfile, or IENS of subfile
FLDVAL(FIL,FLD,IEN,ROOT) ;
I FLD=0!(FLD="#") Q IEN
N PC,ND,DD
S:FLD'=+FLD FLD=+$O(^DD(FIL,"B",FLD,0))
S DD=$G(^DD(FIL,FLD,0))
Q:$P(DD,U,2)["C" $$GET1^DIQ(FIL,IEN_","_$P(ROOT,",",2,999),FLD,"I")
S ND=$P(DD,U,4),PC=$P(ND,";",2),ND=$P(ND,";")
S:$E(ROOT)'=U ROOT=$$ROOT^DILFD(FIL,ROOT,1)
Q $S('$L(ND):"",1:$P($G(@ROOT@(IEN,ND)),U,PC))
; RPC: Lock/unlock a record
; FNUM = File #
; IENS = Record # (IENS format)
; WAIT = If >=0, seconds to wait for lock.
; If missing or null, perform unlock operation.
; DATA = Returns 0 if successful, -n^Error Text if not.
LOCK(DATA,FNUM,IENS,WAIT) ;
N X,IEN,OK,$ET
S @$$TRAP^CIAUOS("LOCKERR^CIAUDDR")
S $ET="",X=$$ROOT^DILFD(FNUM,IENS,1),DATA=0,IEN=+IENS
I '$L(X) S DATA="-1^Table not found" Q
K:$G(WAIT)="" WAIT
D LOCK^CIANBRPC(.OK,$NA(@X@(IEN)),.WAIT)
S:'OK DATA="-2^Record locked by another process"
Q
LOCKERR S DATA="-3^Unexpected error"
Q
; RPC: Convert pointer internal<->external
CVTPTR(DATA,FNUM,VAL,EXT) ;
I EXT S DATA=$$GET1^DIQ(FNUM,VAL,.01)
E D
.N ROOT
.S ROOT=$$ROOT^DILFD(FNUM,,1)
.I '$L(ROOT) S DATA=""
.E I VAL?1"`"1.N D
..S VAL=+$E(VAL,2,999),DATA=$S('VAL:"",$D(@ROOT@(VAL,0))#2:VAL,1:"")
.E D
..N LP
..F LP=0:1:3 S DATA=$$CP(LP) Q:DATA
Q
; Lookup value in "B" xref
CP(XFM) N RTN,LKP
S LKP=$S(XFM#2:$E(VAL,1,30),1:VAL),LKP=$S(XFM\2:$$UP^XLFSTR(LKP),1:LKP),RTN=0
F S RTN=$O(@ROOT@("B",LKP,RTN)) Q:'RTN Q:$P($G(@ROOT@(RTN,0)),U)=VAL
Q RTN
; RPC: Find an entry using specified fields and values
; FNUM = File number to search
; IENS = IENS for subfile
; FLGS = Search flags. Combination of:
; P = partial match
; I = case insensitive
; FLDS = Field #'s or names to search. Can be ;-delimited or list.
; VALS = Values to search. Can be single value or list.
; MAX = Maximum entries to return (default=all)
; Returns list of one or all IENs matching criteria or
; -n^error text if error.
FIND(DATA,FNUM,IENS,FLGS,FLDS,VALS,MAX) ;
N ROOT,QUIT,XRF,XKY,CNT,X
S IENS=$G(IENS)
I $L(IENS),$E(IENS)'="," S IENS=","_IENS
S ROOT=$$ROOT^DILFD(FNUM,IENS,1),QUIT=0,FLGS=$G(FLGS),MAX=+$G(MAX),CNT=0
S:$D(VALS)=1 VALS(1)=VALS
I $D(FLDS)=1 F X=1:1:$L(FLDS,";") S FLDS(X)=$P(FLDS,";",X)
F FLDS=0:0 S FLDS=$O(FLDS(FLDS)) Q:'FLDS D Q:QUIT
.I '$D(VALS(FLDS)) S QUIT="-1^Not enough lookup values." Q
.S X=$$FLDNUM(FNUM,FLDS(FLDS))
.I '$L(X) S QUIT="-2^Unknown field "_FLDS(FLDS)_"." Q
.S FLDS(FLDS)=X
.I '$D(XRF) D
..S X=$$XREF(FNUM,X)
..S:$L(X) XRF=X,XKY=$S(FLGS["I":$$UP^XLFSTR(VALS(FLDS)),1:VALS(FLDS))
I 'QUIT,'$D(XRF) S QUIT="-3^At least one field must be a key field."
D:'QUIT FINDX
I QUIT<0 K @DATA S @DATA@(0)=QUIT
Q
FINDX G FINDN:XRF="#",FINDP:FLGS["P",FINDE
; Find by IEN
FINDN D FINDF(XKY)
Q
; Find exact match
FINDE N XKT,IEN
S IEN=0,XKT=$E(XKY,1,30)
F S IEN=$O(@ROOT@(XRF,XKT,IEN)) Q:'IEN D Q:QUIT
.D FINDF(IEN)
Q
; Partial match
FINDP N XKT,VAL,IEN,LEN
S XKT=$E(XKY,1,30),VAL=XKT,LEN=$L(XKT)
F D S VAL=$O(@ROOT@(XRF,VAL)) Q:$E(VAL,1,LEN)'=XKT!QUIT
.S IEN=0
.F S IEN=$O(@ROOT@(XRF,VAL,IEN)) Q:'IEN D Q:QUIT
..D FINDF(IEN)
Q
; Check fields for match. Add to output if all match
FINDF(IEN) ;
N FND
S FLDS=0,FND=1
F S FLDS=$O(FLDS(FLDS)) Q:'FLDS D Q:'FND
.S FND=$$FINDM(FLDS(FLDS),VALS(FLDS),IEN)
I FND D
.S CNT=CNT+1,@DATA@(CNT)=IEN
.I MAX,CNT'<MAX S QUIT=1
Q
; Check for match
FINDM(FLD,VAL,IEN) ;
N VALX
S VALX=$$FLDVAL(FNUM,FLD,IEN,ROOT)
S:FLGS["I" VAL=$$UP^XLFSTR(VAL),VALX=$$UP^XLFSTR(VALX)
Q $S(FLGS["P":$E(VALX,1,$L(VAL))=VAL,1:VAL=VALX)
; Return field number from name
FLDNUM(FNUM,FLD) ;EP
Q $S(FLD=+FLD:FLD,FLD="#":0,1:$O(^DD(FNUM,"B",FLD,0)))
; Returns the standard xref for the specified field.
XREF(FNUM,FLD,LAST) ;EP
N XREF
S LAST=+$G(LAST),XREF="",FLD=$$FLDNUM(FNUM,FLD)
Q:'$L(FLD) ""
Q:'FLD "#"
F S LAST=$O(^DD(FNUM,FLD,1,LAST)) Q:'LAST I $D(^(LAST,0)),$P(^(0),U,3)="" S XREF=$P(^(0),U,2) Q
Q XREF
; Returns field # if xref is a standard type, or 0 if not.
XREFFLD(FNUM,XREF) ;EP
N FLD,LAST,X
S FLD=$O(^DD(FNUM,0,"IX",XREF,FNUM,0))
Q:'FLD 0
F S X=$$XREF(FNUM,FLD,.LAST) Q:'$L(X)!(X=XREF)
Q $S($L(X):FLD,1:0)
CIAUDDR ;MSC/IND/DKM - FileMan RPC Extensions ;04-May-2006 08:19;DKM
+1 ;;1.2;CIA UTILITIES;;Mar 20, 2007
+2 ;;Copyright 2000-2006, Medsphere Systems Corporation
+3 ;=================================================================
+4 ; RPC: Retrieve DD information about a file.
+5 ; FNUM = File # or name
+6 ; FLDS = Semi-colon delimited field list (optional)
+7 ; IENS = IENS (for subfile entries)
+8 ; FLGS = Control flags:
+9 ; D = Fix duplicate field names
+10 ; M = Retrieve multiples
+11 ; Return data:
+12 ; DATA(0) = -1^Error text or
+13 ; = File #^File name^Rec count^Field count^Readonly^Parent File
+14 ; DATA(n) = Field #^Field name^Datatype^Size^Required^Readonly^Help lines^Xref^Calculated
+15 ; DATA(n,0) = Supplemental data (set mappings)
+16 ; DATA(n,1) = Prompt Text
+17 ; DATA(n,2) = Help Text
GETDD(DATA,FNUM,FLDS,IENS,FLGS) ;
+1 NEW X,Y,Z,CNT,N0,FLD,PF,MULT,DUPS
+2 SET DATA=$NAME(^TMP("CIAUDDR",$JOB))
+3 KILL @DATA
+4 SET FNUM=$GET(FNUM)
SET FLDS=$GET(FLDS)
SET FLGS=$GET(FLGS)
SET MULT=FLGS["M"
SET DUPS=FLGS["D"
+5 IF $LENGTH(FNUM)
IF FNUM'=+FNUM
Begin DoDot:1
+6 SET FNUM=$ORDER(^DIC("B",FNUM,0))
+7 IF FNUM
IF $ORDER(^(FNUM))
SET FNUM=""
End DoDot:1
+8 SET X=$$ROOT^DILFD(FNUM,$GET(IENS),1)
SET PF=$GET(^DD(+FNUM,0,"UP"))
+9 IF $LENGTH(X)
SET X=$GET(@X@(0))
+10 IF PF
SET $PIECE(X,U)=$PIECE($GET(^DD(+FNUM,0)),U)
+11 IF '$LENGTH(X)
DO SETERR("Table not found")
QUIT
+12 SET N0=FNUM_U_$PIECE(X,U)_U_$PIECE(X,U,4)
SET CNT=0
+13 FOR X=1:1:$LENGTH(FLDS,";")
Begin DoDot:1
+14 SET FLD=$PIECE(FLDS,";",X)
+15 IF '$LENGTH(FLD)
QUIT
+16 IF FLD="*"
SET FLD="0-9999999999999999"
+17 IF $TRANSLATE(FLD,".")?1.N1"-"1.N
Begin DoDot:2
+18 SET Z=+$PIECE(FLD,"-")
SET Y=+$PIECE(FLD,"-",2)
+19 IF Z<0
SET Z=0
+20 IF Z=0
IF '$$GETFL(0,0)
SET X=0
+21 IF Z>0
IF $DATA(^DD(FNUM,Z,0))
IF '$$GETFL(Z,MULT)
SET X=0
+22 FOR
IF 'X
QUIT
SET Z=$ORDER(^DD(FNUM,Z))
IF 'Z
QUIT
IF Z>Y
QUIT
IF '$$GETFL(Z,MULT)
SET X=0
End DoDot:2
+23 IF '$TEST
IF '$$GETFL(FLD,1)
SET X=0
End DoDot:1
IF 'X
QUIT
+24 IF X
SET @DATA@(0)=N0_U_CNT_U_($PIECE($GET(^DD(FNUM,0,"DI")),U,2)["Y")_U_PF
+25 QUIT
+26 ; Setup type info for field
+27 ; FLDX = Field # or name
+28 ; MULT = Allow multiples
+29 ; Note: Datatype (TP) maps to TFMFieldType enum:
+30 ; 0 = unknown, 1 = free text, 2 = numeric, 3 = boolean,
+31 ; 4 = date/time, 5 = wp, 6 = pointer, 7 = set, 8 = subfile
GETFL(FLDX,MULT) ;
+1 NEW X,Z,LN,TP,HC,DD,FLD,MLT,NAM
+2 SET FLD=$$FLDNUM(FNUM,FLDX)
SET MLT=0
+3 SET DD=$SELECT('$LENGTH(FLD):"",FLD:$GET(^DD(FNUM,FLD,0)),1:"#^RICJ8,5")
SET X=$PIECE(DD,U,2)
+4 IF '$LENGTH(DD)
DO SETERR("Field not found: "_FLDX)
QUIT 0
+5 IF X
IF $PIECE($GET(^DD(X,.01,0)),U,2)'["W"
SET MLT=1
+6 IF 'MULT
IF MLT
QUIT 1
+7 SET (LN,TP,HC,Z)=0
SET DX=""
SET NAM=$PIECE(DD,U)
SET CNT=CNT+1
+8 IF DUPS
IF $ORDER(^(+$ORDER(^DD(FNUM,"B",NAM,0))))
SET NAM=NAM_"("_FLD_")"
+9 IF MLT
SET TP=8
SET DX=+X
+10 IF '$TEST
IF X["B"
SET TP=3
+11 IF '$TEST
IF X["D"
SET TP=4
SET DX=$PIECE($PIECE($PIECE(DD,U,5),"%DT=",2),"""",2)
+12 IF '$TEST
IF X["F"!(X["K")
SET TP=1
SET LN=+$PIECE($PIECE(DD,U,5),"$L(X)>",2)
IF 'LN
SET LN=30
+13 IF '$TEST
IF X["J"
SET TP=2
SET DX=$PIECE(X,"J",2)
IF DX'[","
SET LN=DX
SET DX=""
SET TP=1
+14 IF '$TEST
IF X["P"!(X["p")
SET TP=6
SET DX=+$PIECE($TRANSLATE(X,"p","P"),"P",2)
SET LN=$$GETLN(DX)
+15 IF '$TEST
IF X["S"
SET TP=7
SET DX=$PIECE(DD,U,3)
+16 IF '$TEST
IF X=+X
SET TP=5
+17 IF 'FLD
SET HC=1
SET @DATA@(CNT,2,HC)="Internal record number."
+18 IF '$TEST
FOR
SET Z=$ORDER(^DD(FNUM,FLD,21,Z))
IF 'Z
QUIT
SET HC=HC+1
SET @DATA@(CNT,2,HC)=^(Z,0)
+19 SET @DATA@(CNT)=FLD_U_NAM_U_TP_U_LN_U_(X["R")_U_(X["I")_U_HC_U_$$XREF(FNUM,FLD)_U_(X["C")
+20 SET @DATA@(CNT,0)=DX
SET @DATA@(CNT,1)=$GET(^DD(FNUM,FLD,3))
+21 QUIT 1
+22 ; Get length of .01 for file
GETLN(FNUM) ;
+1 NEW DD,X
+2 SET DD=$GET(^DD(FNUM,.01,0))
SET X=$PIECE(DD,U,2)
+3 SET X=+$SELECT(X["P":$$GETLN(+$EXTRACT(X,2,99)),X["F":$PIECE($PIECE(DD,U,5),"$L(X)>",2),1:0)
+4 QUIT $SELECT(X:X,1:30)
SETERR(ERR) ;
+1 KILL @DATA
+2 SET @DATA@(0)="-1^"_ERR
+3 QUIT
+4 ; RPC: CIAUDDR MOVETO
+5 ; Move to specified record (returns IEN only)
+6 ; FNUM: File #
+7 ; IEN : Current IEN
+8 ; DIR : 0 = current; 1 = next; 2 = prior
+9 ; IENS: Subfile IENS
+10 ; SCRN: Screens (optional)
+11 ; INDX: Index (optional)
+12 ; Returns IEN or <error code>^<error text>
MOVETO(DATA,FNUM,IEN,DIR,IENS,SCRN,INDX) ;
+1 NEW GBL,IDX,IDF,OK
+2 SET GBL=$$ROOT^DILFD(FNUM,$GET(IENS),1)
SET DIR=+$GET(DIR)
SET INDX=$GET(INDX)
+3 SET DIR=$SELECT(DIR=1:1,DIR=2:-1,1:0)
+4 IF $LENGTH($GET(SCRN))
SET SCRN(-1)=SCRN
+5 IF '$LENGTH(GBL)
SET DATA="-4^Table not found"
QUIT
+6 IF $LENGTH(INDX)
Begin DoDot:1
+7 IF '$ORDER(^DD(FNUM,0,"IX",INDX,""))
SET DATA="-5^Index "_INDX_" not found"
QUIT
+8 SET IDF=$$XREFFLD(FNUM,INDX)
+9 IF 'IDF
SET DATA="-6^Index "_INDX_" is not a standard index"
QUIT
+10 SET IDX=$SELECT(IEN=-1:"",IEN=-2:$CHAR(255),1:$EXTRACT($$FLDVAL(FNUM,IDF,IEN,GBL),1,30))
End DoDot:1
IF $GET(DATA)
QUIT
+11 IF '$TEST
SET IEN=$SELECT(IEN=-1:0,IEN=-2:$ORDER(@GBL@($CHAR(1)),-1)+1,1:+IEN)
+12 FOR
Begin DoDot:1
+13 SET IEN=+$$NXTIEN
+14 ;S OK=IEN&(IEN\1=IEN)&$D(@GBL@(IEN,0)),SCRN=""
+15 SET OK=IEN&$DATA(@GBL@(IEN,0))
SET SCRN=""
+16 FOR
IF 'OK
QUIT
SET SCRN=$ORDER(SCRN(SCRN))
IF '$LENGTH(SCRN)
QUIT
Begin DoDot:2
+17 NEW Y
+18 SET Y=IEN
+19 IF $DATA(@GBL@(Y,0))
+20 XECUTE SCRN(SCRN)
+21 SET OK=$TEST
End DoDot:2
+22 IF 'OK
IF 'DIR
SET IEN=0
End DoDot:1
IF OK!'IEN
QUIT
+23 SET DATA=$SELECT(OK:IEN,'DIR:"-3^Record not found",DIR=1:"-2^End of file",1:"-1^Beginning of file")
+24 QUIT
+25 ; Return next IEN
NXTIEN() IF 'DIR
QUIT IEN
+1 IF '$LENGTH(INDX)
QUIT $ORDER(@GBL@(IEN),DIR)
+2 NEW OK
+3 FOR
Begin DoDot:1
+4 IF IEN'>0
SET IDX=$ORDER(@GBL@(INDX,IDX),DIR)
SET IEN=""
+5 SET IEN=$SELECT($LENGTH(IDX):$ORDER(@GBL@(INDX,IDX,IEN),DIR),1:0)
+6 ;S OK=$S('IEN:0,1:$E($$FLDVAL(FNUM,IDF,IEN,GBL),1,30)=IDX)
+7 SET OK=$SELECT('IEN:0,1:$DATA(@GBL@(IEN,0)))
End DoDot:1
IF OK!'$LENGTH(IDX)
QUIT
+8 QUIT IEN
+9 ; Return field value (internal)
+10 ; FIL = File or subfile #
+11 ; FLD = Field #
+12 ; IEN = Record #
+13 ; ROOT = Global root of file or subfile, or IENS of subfile
FLDVAL(FIL,FLD,IEN,ROOT) ;
+1 IF FLD=0!(FLD="#")
QUIT IEN
+2 NEW PC,ND,DD
+3 IF FLD'=+FLD
SET FLD=+$ORDER(^DD(FIL,"B",FLD,0))
+4 SET DD=$GET(^DD(FIL,FLD,0))
+5 IF $PIECE(DD,U,2)["C"
QUIT $$GET1^DIQ(FIL,IEN_","_$PIECE(ROOT,",",2,999),FLD,"I")
+6 SET ND=$PIECE(DD,U,4)
SET PC=$PIECE(ND,";",2)
SET ND=$PIECE(ND,";")
+7 IF $EXTRACT(ROOT)'=U
SET ROOT=$$ROOT^DILFD(FIL,ROOT,1)
+8 QUIT $SELECT('$LENGTH(ND):"",1:$PIECE($GET(@ROOT@(IEN,ND)),U,PC))
+9 ; RPC: Lock/unlock a record
+10 ; FNUM = File #
+11 ; IENS = Record # (IENS format)
+12 ; WAIT = If >=0, seconds to wait for lock.
+13 ; If missing or null, perform unlock operation.
+14 ; DATA = Returns 0 if successful, -n^Error Text if not.
LOCK(DATA,FNUM,IENS,WAIT) ;
+1 NEW X,IEN,OK,$ETRAP
+2 SET @$$TRAP^CIAUOS("LOCKERR^CIAUDDR")
+3 SET $ETRAP=""
SET X=$$ROOT^DILFD(FNUM,IENS,1)
SET DATA=0
SET IEN=+IENS
+4 IF '$LENGTH(X)
SET DATA="-1^Table not found"
QUIT
+5 IF $GET(WAIT)=""
KILL WAIT
+6 DO LOCK^CIANBRPC(.OK,$NAME(@X@(IEN)),.WAIT)
+7 IF 'OK
SET DATA="-2^Record locked by another process"
+8 QUIT
LOCKERR SET DATA="-3^Unexpected error"
+1 QUIT
+2 ; RPC: Convert pointer internal<->external
CVTPTR(DATA,FNUM,VAL,EXT) ;
+1 IF EXT
SET DATA=$$GET1^DIQ(FNUM,VAL,.01)
+2 IF '$TEST
Begin DoDot:1
+3 NEW ROOT
+4 SET ROOT=$$ROOT^DILFD(FNUM,,1)
+5 IF '$LENGTH(ROOT)
SET DATA=""
+6 IF '$TEST
IF VAL?1"`"1.N
Begin DoDot:2
+7 SET VAL=+$EXTRACT(VAL,2,999)
SET DATA=$SELECT('VAL:"",$DATA(@ROOT@(VAL,0))#2:VAL,1:"")
End DoDot:2
+8 IF '$TEST
Begin DoDot:2
+9 NEW LP
+10 FOR LP=0:1:3
SET DATA=$$CP(LP)
IF DATA
QUIT
End DoDot:2
End DoDot:1
+11 QUIT
+12 ; Lookup value in "B" xref
CP(XFM) NEW RTN,LKP
+1 SET LKP=$SELECT(XFM#2:$EXTRACT(VAL,1,30),1:VAL)
SET LKP=$SELECT(XFM\2:$$UP^XLFSTR(LKP),1:LKP)
SET RTN=0
+2 FOR
SET RTN=$ORDER(@ROOT@("B",LKP,RTN))
IF 'RTN
QUIT
IF $PIECE($GET(@ROOT@(RTN,0)),U)=VAL
QUIT
+3 QUIT RTN
+4 ; RPC: Find an entry using specified fields and values
+5 ; FNUM = File number to search
+6 ; IENS = IENS for subfile
+7 ; FLGS = Search flags. Combination of:
+8 ; P = partial match
+9 ; I = case insensitive
+10 ; FLDS = Field #'s or names to search. Can be ;-delimited or list.
+11 ; VALS = Values to search. Can be single value or list.
+12 ; MAX = Maximum entries to return (default=all)
+13 ; Returns list of one or all IENs matching criteria or
+14 ; -n^error text if error.
FIND(DATA,FNUM,IENS,FLGS,FLDS,VALS,MAX) ;
+1 NEW ROOT,QUIT,XRF,XKY,CNT,X
+2 SET IENS=$GET(IENS)
+3 IF $LENGTH(IENS)
IF $EXTRACT(IENS)'=","
SET IENS=","_IENS
+4 SET ROOT=$$ROOT^DILFD(FNUM,IENS,1)
SET QUIT=0
SET FLGS=$GET(FLGS)
SET MAX=+$GET(MAX)
SET CNT=0
+5 IF $DATA(VALS)=1
SET VALS(1)=VALS
+6 IF $DATA(FLDS)=1
FOR X=1:1:$LENGTH(FLDS,";")
SET FLDS(X)=$PIECE(FLDS,";",X)
+7 FOR FLDS=0:0
SET FLDS=$ORDER(FLDS(FLDS))
IF 'FLDS
QUIT
Begin DoDot:1
+8 IF '$DATA(VALS(FLDS))
SET QUIT="-1^Not enough lookup values."
QUIT
+9 SET X=$$FLDNUM(FNUM,FLDS(FLDS))
+10 IF '$LENGTH(X)
SET QUIT="-2^Unknown field "_FLDS(FLDS)_"."
QUIT
+11 SET FLDS(FLDS)=X
+12 IF '$DATA(XRF)
Begin DoDot:2
+13 SET X=$$XREF(FNUM,X)
+14 IF $LENGTH(X)
SET XRF=X
SET XKY=$SELECT(FLGS["I":$$UP^XLFSTR(VALS(FLDS)),1:VALS(FLDS))
End DoDot:2
End DoDot:1
IF QUIT
QUIT
+15 IF 'QUIT
IF '$DATA(XRF)
SET QUIT="-3^At least one field must be a key field."
+16 IF 'QUIT
DO FINDX
+17 IF QUIT<0
KILL @DATA
SET @DATA@(0)=QUIT
+18 QUIT
FINDX IF XRF="#"
GOTO FINDN
IF FLGS["P"
GOTO FINDP
GOTO FINDE
+1 ; Find by IEN
FINDN DO FINDF(XKY)
+1 QUIT
+2 ; Find exact match
FINDE NEW XKT,IEN
+1 SET IEN=0
SET XKT=$EXTRACT(XKY,1,30)
+2 FOR
SET IEN=$ORDER(@ROOT@(XRF,XKT,IEN))
IF 'IEN
QUIT
Begin DoDot:1
+3 DO FINDF(IEN)
End DoDot:1
IF QUIT
QUIT
+4 QUIT
+5 ; Partial match
FINDP NEW XKT,VAL,IEN,LEN
+1 SET XKT=$EXTRACT(XKY,1,30)
SET VAL=XKT
SET LEN=$LENGTH(XKT)
+2 FOR
Begin DoDot:1
+3 SET IEN=0
+4 FOR
SET IEN=$ORDER(@ROOT@(XRF,VAL,IEN))
IF 'IEN
QUIT
Begin DoDot:2
+5 DO FINDF(IEN)
End DoDot:2
IF QUIT
QUIT
End DoDot:1
SET VAL=$ORDER(@ROOT@(XRF,VAL))
IF $EXTRACT(VAL,1,LEN)'=XKT!QUIT
QUIT
+6 QUIT
+7 ; Check fields for match. Add to output if all match
FINDF(IEN) ;
+1 NEW FND
+2 SET FLDS=0
SET FND=1
+3 FOR
SET FLDS=$ORDER(FLDS(FLDS))
IF 'FLDS
QUIT
Begin DoDot:1
+4 SET FND=$$FINDM(FLDS(FLDS),VALS(FLDS),IEN)
End DoDot:1
IF 'FND
QUIT
+5 IF FND
Begin DoDot:1
+6 SET CNT=CNT+1
SET @DATA@(CNT)=IEN
+7 IF MAX
IF CNT'<MAX
SET QUIT=1
End DoDot:1
+8 QUIT
+9 ; Check for match
FINDM(FLD,VAL,IEN) ;
+1 NEW VALX
+2 SET VALX=$$FLDVAL(FNUM,FLD,IEN,ROOT)
+3 IF FLGS["I"
SET VAL=$$UP^XLFSTR(VAL)
SET VALX=$$UP^XLFSTR(VALX)
+4 QUIT $SELECT(FLGS["P":$EXTRACT(VALX,1,$LENGTH(VAL))=VAL,1:VAL=VALX)
+5 ; Return field number from name
FLDNUM(FNUM,FLD) ;EP
+1 QUIT $SELECT(FLD=+FLD:FLD,FLD="#":0,1:$ORDER(^DD(FNUM,"B",FLD,0)))
+2 ; Returns the standard xref for the specified field.
XREF(FNUM,FLD,LAST) ;EP
+1 NEW XREF
+2 SET LAST=+$GET(LAST)
SET XREF=""
SET FLD=$$FLDNUM(FNUM,FLD)
+3 IF '$LENGTH(FLD)
QUIT ""
+4 IF 'FLD
QUIT "#"
+5 FOR
SET LAST=$ORDER(^DD(FNUM,FLD,1,LAST))
IF 'LAST
QUIT
IF $DATA(^(LAST,0))
IF $PIECE(^(0),U,3)=""
SET XREF=$PIECE(^(0),U,2)
QUIT
+6 QUIT XREF
+7 ; Returns field # if xref is a standard type, or 0 if not.
XREFFLD(FNUM,XREF) ;EP
+1 NEW FLD,LAST,X
+2 SET FLD=$ORDER(^DD(FNUM,0,"IX",XREF,FNUM,0))
+3 IF 'FLD
QUIT 0
+4 FOR
SET X=$$XREF(FNUM,FLD,.LAST)
IF '$LENGTH(X)!(X=XREF)
QUIT
+5 QUIT $SELECT($LENGTH(X):FLD,1:0)