home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- *
- * Name: STRUCREC() - Extension UDF() to Clipper Debugger
- * Description: Performs DISP STRUC and allows View/Edit of any record
- * Author: Philip H. Schwartz
- * Audience: Nantucket DEVCON '90
- * Written: June 4, 1990
- * Compiler: Clipper 5.0 V7.7 BETA
- * Comp Option: /B
- * Linker: RTLink Version 1.3 (Clipper)
- * Library: clipper, extend
- * Obj Module:
- * Link input: rtlink fi example3 out example3 li clipper,extend,cld
- * Headers: STD.ch
- * Copyright: (c) 1990 Philip H. Schwartz
- * Rights: All Commercial & Publishing Rights Reserved
- *
- *********************************************************************/
-
- #include "achoice.ch"
- #include "inkey.ch"
-
- #define DEMO // remove this to compile UDF only
-
- /* Defines for DBSTRUCT() array */
- #define ARR_NAME 1
- #define ARR_TYPE 2
- #define ARR_LEN 3
- #define ARR_DEC 4
-
- /* Define for DIRECTRY() function */
- #define F_NAME 1
-
- #ifdef DEMO
- /* The test program consists of the following line */
- WAIT // wait state to invoke debugger
- RETURN
- #endif
-
- FUNCTION StrucRec
- LOCAL cFuncScreen,aStruct,aStruct2,aStruct3,aFlds,nChoice,cScreenSave,;
- aFiles,aNames,cPicture,i
- PRIVATE nRecNum,nRelWindow
-
- cFuncScreen=SAVESCREEN(0,0,24,79) // save Debugger screen
- CLS
- aFiles:=DIRECTORY("*.dbf") // creates nested array
-
- /* Convert DIRECTORY() file name data to format that
- can be used by ACHOICE, i.e. a single array of names. We will
- use the AEVAL array/codeblock function to do this. */
- aNames:={}
- AEVAL(aFiles, {|file| AADD(aNames,file[F_NAME])})
-
- DO WHILE .t.
-
- cScreenSave=SAVESCREEN(1,0,10,14) // save the ACHOICE screen area
- @ 1,0 TO 10,14 DOUBLE // draw ACHOICE frame
- nChoice=ACHOICE(2,1,9,13,aNames) // select one of the DBF files
- RESTSCREEN(1,0,10,14,cScreenSave) // restore the ACHOICE screen area
-
- IF nChoice=0 // check for ESC
- EXIT // and EXIT
- ENDIF // the routine
-
- cFileName=TRIM(aNames[nChoice]) // pick up the file name
- USE(cFileName) NEW // open file in a new work area
- aStruct:=DBSTRUCT() // get structure information
- aStruct2:=ARRAY(LEN(aStruct)) // make 2nd array
-
- /* Fill the 2nd array with formatted STRUC information */
- FOR i=1 TO LEN(aStruct)
- aStruct2[i]=STR(i,3)+" "+PAD(aStruct[i,ARR_NAME],10)+SPACE(1)+;
- aStruct[i,ARR_TYPE]+SPACE(3)+STR(aStruct[i,ARR_LEN],2)+SPACE(1)+;
- IIF(aStruct[i,ARR_TYPE]!="N",SPACE(2),STR(aStruct[i,ARR_DEC],2))
- NEXT
-
- /* Use ACHOICE to display the formatted STRUC information for
- this file. We don't actually care what the user highlights.
- We will however, check for ESC. */
- cScreenSave=SAVESCREEN(1,0,10,30) // save ACHOICE screen
- @ 1,0 TO 10,30 DOUBLE // draw the frame
- nChoice=ACHOICE(2,1,9,29,aStruct2) // allow user to scroll through struc
- RESTSCREEN(1,0,10,30,cScreenSave) // restore ACHOICE screen
-
- IF nChoice!=0 .AND. LASTREC()>0
- aStruct3:=ARRAY(LEN(aStruct)) // make 3rd array for RECORD info
- cScreenSave=SAVESCREEN(0,0,24,79) // save ACHOICE screen
- nRecNum=1 // start with RECNO()=1
-
- @ 02,0 SAY REPLICATE(CHR(196),80)
- @ 23,0 SAY REPLICATE(CHR(196),80)
- @ 24,0 SAY 'Please make a selection: '+;
- CHR(24)+CHR(25)+" "+CHR(26)+CHR(27)+" "+CHR(17)+CHR(196)+CHR(217)+;
- ' PgUp PgDn Home End or ESC to Exit'
- DO WHILE .t.
- GOTO nRecNum // go to selected RECNO()
- @ 1,0 // blank out line
- @ 1,0 SAY TRIM(cFileName)+" Record # "+LTRIM(STR(nRecNum,6))+;
- " of "+LTRIM(STR(LASTREC()))
-
- /* Fill the array with formatted RECORD information */
- FOR i=1 TO LEN(aStruct)
- aStruct3[i]=STR(i,3)+" "+PAD(aStruct[i,ARR_NAME],10)+": "+;
- ALLTRIM(FldFmt(aStruct[i,ARR_NAME]))
- NEXT
-
- /* Let the user select a record to view or field to update */
- nChoice=ACHOICE(3,0,22,79,aStruct3,,'user_rtn',nChoice)
- DO CASE
- /* If a field was selected for editing, check to see if it
- is a numeric variable and create a PIC template for it */
- CASE LASTKEY()=K_RETURN
- IF aStruct[nchoice,ARR_TYPE]='N'
- cPicture=REPLICATE("9",aStruct[nChoice,ARR_LEN])+;
- IIF(aStruct[nChoice,ARR_DEC]=0,"","."+;
- REPLICATE("9",aStruct[nChoice,ARR_DEC]))
- ELSE
- cPicture=NIL
- ENDIF
-
- /* Update the field */
- FldEdit(aStruct[nchoice,ARR_NAME],nchoice,cPicture)
-
- /* Check for ESC and exit */
- CASE LASTKEY()=K_ESC
- EXIT
- ENDCASE
- ENDDO
- RESTSCREEN(0,0,24,79,cScreenSave) // restore ACHOICE screen
- ENDIF
- ENDDO
- RESTSCREEN(0,0,24,79,cFuncScreen) // remember original screen
- RETURN NIL
-
- /* This function formats the fields of a DBF for display
- based on the variable type */
- FUNCTION FldFmt
- PARAMETER FldName
- DO CASE
- CASE VALTYPE(&FldName)="C"
- RETURN(PAD(&FldName,MIN(LEN(&FldName),80)))
- CASE VALTYPE(&FldName)="D"
- RETURN(DTOC(&FldName))
- CASE VALTYPE(&FldName)="N"
- RETURN(STR(&FldName))
- CASE VALTYPE(&FldName)="M"
- RETURN("MEMO")
- CASE VALTYPE(&FldName)="L"
- RETURN(IIF(&FldName,"TRUE","FALSE"))
- ENDCASE
- RETURN NIL
-
- /* This function allows a user to edit any field in the
- selected DBF. Since the field count may have exceeded
- the screen size and ACHOICE automatically scrolls array
- elements, it is necessary to use the ACHOICE user function
- to tell us the relative position in the window for the
- selected element. This value is stored in nRelWindow. */
- FUNCTION FldEdit
- PARAMETER cFldName,nElement,cPicture
- PRIVATE cMacFld
- cMacFld:=cFldName // assign to PRIVATE for & GET
- SET DELIMITER OFF
- DO CASE
- CASE VALTYPE(&cMacFld)="C"
- @ 3+nRelWindow,18 GET &cMacFld PICTURE '@k'
- CASE VALTYPE(&cMacFld)="D"
- @ 3+nRelWindow,18 GET &cMacFld PICTURE '@d'
- CASE VALTYPE(&cMacFld)="N"
- @ 3+nRelWindow,18 GET &cMacFld PICTURE(cPicture)
- CASE VALTYPE(&cMacFld)="L"
- @ 3+nRelWindow,18 GET &cMacFld PICTURE 'L'
- ENDCASE
- READ
- RETURN NIL
-
- /* This is the user function exit for the ACHOICE that we use
- to inspect/edit individual records. Its main function is to
- keep track of the current element's relative position in the window.
- It also is where we check for BOF(), EOF() and move the record
- pointer up or down. */
- FUNCTION user_rtn
- PARAMETER nMode,nCurElement,nRelPosition
- nRelWindow:=nRelPosition
- DO CASE
- CASE nMode=AC_IDLE // check for IDLE state
- RETURN(AC_CONT) // yes, continue
- CASE nMode=AC_HITTOP .OR. ; // check for -SKIP BOF() state
- nMode=AC_HITBOTTOM // or SKIP EOF() state
- TONE(500,1) // beep
- RETURN(AC_CONT) // and continue
- CASE nMode=AC_EXCEPT // check for KEY EXCEPTION
- DO CASE
- CASE LASTKEY()=K_LEFT // check for left arrow
- nRecNum=MAX(--nRecNum,1) // yes, previous record
- RETURN(AC_SELECT) // and select
- CASE LASTKEY()=K_RIGHT // check for right arrow
- nRecNum=MIN(++nRecNum,LASTREC()) // yes, next record
- RETURN(AC_SELECT) // and select
- CASE LASTKEY()=K_RETURN // check for RETURN
- RETURN(AC_SELECT) // yes, select
- CASE LASTKEY()=K_ESC // check for ESC
- RETURN(AC_ABORT) // yes, abort
- CASE LASTKEY()=K_HOME // check for HOME
- nRecNum=1 // yes, GO TOP
- RETURN(AC_SELECT) // and select
- CASE LASTKEY()=K_END // check for END
- nRecNum=LASTREC() // yes, GO BOTTOM
- RETURN(AC_SELECT) // and select
- ENDCASE
- CASE nMode=AC_NOITEM // check for NO ITEM state
- RETURN(AC_CONT) // yes, continue
- ENDCASE
- RETURN(AC_CONT)
- /*EOF*/