// // INIFILE.VDM Ch. Ziemski 17.11.2002 // 24.11.2002 // // // Provides some functions for using INI-files in your macros. // // You can easily read/write strings or numerical values from/to an INI-file. // //--------------------------------------------------------------------------- // // Input parameters: // // // $103 : (READ_STR, "section", "key", r, "text" [, "inifile"]) // (READ_NUM, "section", "key", r, n [, "inifile"]) // // (WRITE_STR, "section", "key", "text" [, "inifile"]) // (WRITE_NUM, "section", "key", n [, "inifile"]) // // (DELETE, "section", "key" [, "inifile"]) // // "text" could also be: @r // r could also be: #n // n could also be: #n // Allowed string delimiters: "'`´^/ // // The optional inifile-name is used as follows: // // if not given: // defaults to "VED-MAC.INI" in the current directory // // if only a filename: // search file in "current directory" -> USER_MACRO -> MACRO -> HOME // and use the path of the found one // // if containing a directory: // absolute: that path will be used // relative: path from current directory on will be used // // if INI file not found: // using READ_ : simply returns default values from call and ReturnValue= -2 // using WRITE_: creates INI file // // // // Return Values: // // -2 : read: default used because: INI file not found // -1 : read: default used because: section/key not found // // 0 : o.k. // 1 : parameter error // // 3 : write: could not create/write to INI ??? how to check error? not implemented yet! // //-------------------------------------------------------------------------- // // All parameters must have the correct type (string or numerical). // Otherwise the macro returns an error. // // // #r is set with: READ_NUM : the read value of given key in given section // READ_STR : - // // T-Reg(r) is set: READ_NUM : the read numerical value converted to a string // READ_STR : the read value of given key in given section // // // Special cases: // // If the "section" parameter is an empty string "", all sections are read // from the INI-file to the T-Reg r. // #r is set to the number of sections found // // If the "key" parameter is an empty string "", all keys of the given // section are read from the INI-file to the T-Reg r. // #r is set to the number of keys found // // //------------------------------------------------------------------------------ // // ToDo: // Some optimization // check whether INI file is already loaded // a bit beautifying // if key empty: delete whole section ?? (only if emty?) ??? // //------------------------------------------------------------------------------ // // #90 : function: 1 = read 2 = write // #91 : type: 1 = numeric 2 = string // #93 : register# to read from / to write into // #94 : num value // // #97 : Return Value // #98 : temp CP // #99 : temp CP // // #103 : temp // #104 : temp // #106 : Buf Num // // $90 : INI filename with full path // $91 : INI filename (only name) // $92 : section // $93 : key // $94 : text string // // $103 : temp // $104 : temp // $105 : temp for filename // //============================================================================= Num_Push(90,99) Reg_Push(90,94) #106=Buf_Num Buf_Switch(Buf_Free, EXTRA) if(Reg_Size(103) < 14){ // minimal possible size of the parameters #97=1 Goto MEXIT } // build the registers from the parameters Buf_Empty(OK) Reg_Ins(103) BoF Replace("|<|W", "", BEGIN+ALL+NOERR) // delete possible leading and trailing whitespace Replace("|W|>", "", BEGIN+ALL+NOERR) BoF if(Match("|[|X](", ADVANCE) != 0){ #97=1 // param error Goto MEXIT } // the function to execute Match("|[|X]", ADVANCE) if(Match("|{READ,WRITE,DELETE}", ADVANCE) != 0){ #97=1 // param error Goto MEXIT } #90=Match_Item // Function READ/WRITE if(#90 < 3){ // if not Function DELETE if(Match("|[_]|{NUM,STR}", ADVANCE) != 0){ #97=1 // param error Goto MEXIT } #91=Match_Item // Sub-Function NUM/STR } if(Match("|[|X],", ADVANCE) != 0){ #97=1 // param error Goto MEXIT } Call("GET_PAR_STR") // section if(#97 != 0){ Goto MEXIT } Reg_Set(92, @103) if(Match("|[|X],", ADVANCE) != 0){ #97=1 Goto MEXIT } Call("GET_PAR_STR") // key if(#97 != 0){ Goto MEXIT } Reg_Set(93, @103) // the parameters depending on the function if(#90 == 1){ // READ if(Match("|[|X],", ADVANCE) != 0){ #97=1 Goto MEXIT } Call("GET_PAR_NUM") // register# if(#97 != 0){ Goto MEXIT } #93 = Return_Value if(Match("|[|X],", ADVANCE) != 0){ #97=1 Goto MEXIT } if(#91 == 1){ // default Call("GET_PAR_NUM") if(#97 != 0){ Goto MEXIT } #94 = Return_Value }else{ Call("GET_PAR_STR") if(#97 != 0){ Goto MEXIT } Reg_Set(94, @103) } }else{ if(#90 == 2){ // WRITE if(Match("|[|X],", ADVANCE) != 0){ #97=1 Goto MEXIT } if(#91 == 1){ Call("GET_PAR_NUM") // num value to write if(#97 != 0){ Goto MEXIT } #94 = Return_Value }else{ Call("GET_PAR_STR") // string to write if(#97 != 0){ Goto MEXIT } Reg_Set(94, @103) } } } Reg_Empty(105) if(Match("|[|X],", ADVANCE) == 0){ // if another comma => paramter Call("GET_PAR_STR") // inifile name if(#97 != 0){ Goto MEXIT } Reg_Set(105, @103) } if(Match("|[|X])", ADVANCE) != 0){ // closing patenthesis found ? #97=1 // param error Goto MEXIT } // build the filename if(Reg_Size(105) == 0){ Reg_Set(105, "VED-MAC.INI") // set default } Buf_Empty(OK) Reg_Ins(105) // filename Search("\", BEGIN+NOERR) if(EM){ // if no path included: search in some directories if(File_Exist("|@(105)")){ Reg_Set(90, CUR_DIR) }else{ if(File_Exist("|(USER_MACRO)\|@(105)")){ Reg_Set(90, USER_MACRO) }else{ if(File_Exist("|(MACRO)\|@(105)")){ Reg_Set(90, MACRO) }else{ if(File_Exist("|(HOME)\|@(105)")){ Reg_Set(90, HOME) }else{ Reg_Set(90, ".") } } } } Reg_Set(90, "\", APPEND) Reg_Set(90, @105, APPEND) }else{ // if path included BoF if(Match("|{\,|A:\}") != 0){ // if relative path Reg_Set(90, CUR_DIR) // use current dir plus given subdirectory Reg_Set(90, "\", APPEND) Reg_Set(90, @105, APPEND) }else{ // if absolute path Reg_Set(90, @105) // just use it } } //----------------------------------------------------------- Reg_Empty(103) Buf_Empty(OK) if(#90 == 1){ // read if(File_Exist("|@(90)")){ File_Open("|@(90)", FORCE+NOEVENT) Replace("|<|X|N", "", BEGIN+ALL+NOERR) // delete possible empty lines if(Reg_Size(92) == 0){ // if no section given: get sections BoF #104=0 // Counter for sections in file Reg_Empty(94) while(! At_EoF){ if(Cur_Char == 91){ Reg_Copy(94, 1, APPEND) #104++ } Line(1, NOERR) } #91=2 // it's a string #@93=#104 // but save count into the num variable too #97=0 // o.k. }else{ Search("[|@(92)]", BEGIN+NOERR) // search section if(!EM){ Line(1, NOERR) #98=CP if(! At_EoF){ Search("|<[", NOERR) // search next section if(EM){ EoF } #99=CP // begin of next section or EoF Goto_Pos(#98) // begin of current section if(Reg_Size(93) == 0){ // if no key given: get keys of that section #104=0 // counter for keys in current section Reg_Empty(94) while(Cur_Pos < #99){ // while in current block if(Cur_Char != 59){ // if not comment char: semicolon Search("=") Reg_Copy_Block(94, BoL_Pos, Cur_Pos, APPEND) // get key without value Out_Reg(94, APPEND) Type_Newline(1) Out_Reg(CLEAR) #104++ } Line(1, NOERR) } #91=2 // it's a string #@93=#104 // but save count into the num variable too #97=0 // o.k. }else{ Search_Block("|<|@(93)=", #98, #99, BEGIN+ADVANCE+NOERR) // search key if(!EM){ Reg_Copy_Block(94, Cur_Pos, EoL_Pos) #94=Num_Eval_Reg(94, SUPPRESS) Reg_Set(#93, @94) // store it as string too for convenience #97=0 // o.k. }else{ #97=-1 // default used because: section/key not found } } } }else{ #97=-1 // default used because: section/key not found } } }else{ #97=-2 // used default: INI file no found } if(#91 == 1){ #@93 = #94 }else{ Reg_Set(#93, @94) } Goto MEXIT //----------------------------------------------------------- }else{ if(#90 == 2){ // write if(File_Exist("|@(90)")){ File_Open("|@(90)", FORCE+NOEVENT) Search("[|@(92)]", BEGIN+NOERR) // search section if(!EM){ // if found Line(1, NOERR) // determine begin and end of section #98=CP if(!At_EoF){ Search("|<[", NOERR) // look for next section begin if(EM){ // if no found EoF if(! At_BoL){ // be sure to have a trailing CR/LF Ins_Newline(1) } } } #99=CP Search_Block("|<|@(93)=", #98, #99, BEGIN+ADVANCE+NOERR) // search key if(!EM){ // if found Del_Block(Cur_Pos, EoL_Pos) if(#91 == 1){ // NUM Num_Ins(#94, LEFT+NOCR) // write new value }else{ // STR Reg_Ins(94) // write new value } #97=0 // return value }else{ // create and write key Goto_Pos(#99) // end of current section Reg_Ins(93) Ins_Text("=") if(#91 == 1){ Num_Ins(#94, LEFT+NOCR) }else{ Reg_Ins(94) } Ins_Newline(1) #97=0 // o.k. } }else{ // if section not found: create section and write key EoF if(! At_BoL){ // be sure to have a trailing CR/LF Ins_Newline(1) } Ins_Text("[") Reg_Ins(92) Ins_Text("]") Ins_Newline(1) Reg_Ins(93) Ins_Text("=") if(#91 == 1){ Num_Ins(#94, LEFT+NOCR) }else{ Reg_Ins(94) } Ins_Newline(1) #97=0 // o.k. } }else{ // create file with entry Ins_Text("[") Reg_Ins(92) Ins_Text("]") Ins_Newline(1) Reg_Ins(93) Ins_Text("=") if(#91 == 1){ Num_Ins(#94, LEFT+NOCR) }else{ Reg_Ins(94) } Ins_Newline(1) File_Save_As("|@(90)", NOMSG) #97=0 } File_Save(NOMSG) }else{ if(#90 == 3){ // Function DELETE File_Open("|@(90)", FORCE+NOEVENT) Search("[|@(92)]", BEGIN+NOERR) // search section if(!EM){ Line(1, NOERR) #98=CP if(!At_EoF){ Search("|<[", NOERR) if(EM){ EoF } #99=CP Search_Block("|<|@(93)=", #98, #99, BEGIN+ADVANCE+NOERR) // search key if(!EM){ BoL Del_Line(1) #97=0 // return value File_Save(NOMSG) Reg_Empty(#93) #@93=0 } } } } } } //-------------------------- :MEXIT: #103=#97 // return value // Optional error dialog, should be better placed in the calling macro... // // Num_Str(#103, 103, LEFT) // // if(#103 > 0){ // Dialog_Input_1(1,"`Error`, // `Parameter error`, // `Return Code = |@(103)`", // APP+CENTER,0,0) // } Reg_Pop(90,94) Num_Pop(90,99) Buf_Quit(OK) Buf_Switch(#106) return(#103) //---------------------------------------------------------------------------- :GET_PAR_STR: // // returns: #93 = 0 : o.k. // #93 = 1 : param error // $103 : string // // uses add.: // #103 #97=0 Match("|[|X]", ADVANCE) if(Match("@", ADVANCE) != 0){ if(Match(&|{",',`,´,^,/}&) != 0){ #97=1 // param error return }else{ Reg_Copy_Block(104, Cur_Pos, Cur_Pos+1) // get the current string delimiter Char(1) #103=Cur_Pos Search("|@(104)", ADVANCE+NOERR) // search the closing delimiter if(EM){ #97=1 // param error return } Reg_Copy_Block(103, #103, Cur_Pos-1) } }else{ if(Match("|D") != 0){ #97=1 // param error return }else{ #103=Num_Eval(SUPPRESS+ADVANCE) Reg_Set(103, @#103) } } return(0) //---------------------------------------------------------------------------- :GET_PAR_NUM: // // returns: Return_Value : register# to read from / to write into // #97 = 0 : o.k // #97 = 1 : param error // uses: #103 // Match("|[|X]", ADVANCE) if(Match("|{#,|D}") != 0){ #97=1 // param error return(0) } #97=0 if(Match_Item == 1){ Char(1) #103=Num_Eval(SUPPRESS+ADVANCE) #103=#@103 }else{ #103=Num_Eval(SUPPRESS+ADVANCE) } return(#103) //=============================================================================