/******************************************* Module DBeditor Editor Version: 1.0 Author: Thierry LEFORT Last update: 05/21/2001 *******************************************/ typeof EditorWin = ObjWin ;; /*The editor Window*/ typeof font = ObjFont ;; typeof ed = Editor ;; typeof Alias = S ;; /*ODBC variables*/ typeof Login = S ;; typeof Password = S ;; typeof db= SqlDB ;; /*Data Base*/ typeof table = S ;; /*Labels*/ typeof AliasTexte = ObjText ;; typeof AliasEditTexte = ObjText ;; typeof TableTexte = ObjText ;; typeof MetaTable = S ;; typeof MetaTableAttr = S ;; typeof labelMetaInd = ObjText ;; typeof labelMetaTable = ObjText ;; /*Buttons for DB acces*/ typeof FullAccessBttn = ObjButton ;; typeof ReadAccessBttn = ObjButton ;; typeof NoAccessBttn = ObjButton ;; typeof PrimariKeyBttn = ObjButton ;; typeof ConnectBtn = ObjButton ;; typeof comboBoxindTab = ObjBox;; typeof comboBoxindAttr = ObjBox;; typeof comboBox = ObjBox;; typeof TableModifButtn = ObjButton ;; typeof OdbcModifButtn = ObjButton ;; typeof MultiListe = ObjListTab ;; typeof ListAccess = [I r1] ;; typeof listsel = [I r1] ;; typeof LISTEATTRIBUTSBDD = [[S r1] r1];; typeof check = ObjCheck ;; /*typeof PopUpMenu = ObjMenu ;;*/ var FULLACCESS = 0 ;; var READONLY = 1 ;; var NOACCESS = 2 ;; var KEY = 3 ;; var OnOff = 1;; var firstuse = 0;; /*0 if it's the first openning of the editor, 1 if not*/ /*Looks in a SR1R1 if the first element of each list is the same of "table"*/ fun IsThisTableExist (table, liste)= if liste == nil then 0 else let hd hd liste -> tableToCmp in if !strcmp table tableToCmp then 1 else IsThisTableExist table tl liste ;; fun convertIR1TOSR1R1 (listIR1) = if listIR1 == nil then nil else ((itoa hd listIR1)::nil)::(convertIR1TOSR1R1 tl listIR1) ;; fun convertSR1R1TOIR1 (listSR1R1) = if listSR1R1 == nil then nil else (atoi hd hd listSR1R1)::(convertSR1R1TOIR1 tl listSR1R1) ;; /*fill a line with a Sr1*/ fun fill_Line (theListe, listSR1, column, line, type) = if listSR1 == nil then 1 else ( if type == 1 then ( _ADDlistTabItem theListe line column hd listSR1 ) else ( _SETlistTabItem theListe line column hd listSR1; ); fill_Line theListe tl listSR1 column+1 line 0; 0 ) ;; fun MakeAccessListe (AccessListe) = if AccessListe ==nil then nil else ( let hd AccessListe -> Access in if Access == FULLACCESS then ((_locEditor "DB_FULLACCESS" nil)::nil)::(MakeAccessListe tl AccessListe) else if Access == READONLY then ((_locEditor "DB_READONLY" nil)::nil)::(MakeAccessListe tl AccessListe) else if Access == NOACCESS then ((_locEditor "DB_NOACCESS" nil)::nil)::(MakeAccessListe tl AccessListe) else if Access == KEY then ((_locEditor "DB_KEY" nil)::nil)::(MakeAccessListe tl AccessListe) else nil ) ;; /*Fill the ListTab with a Sr1r1*/ fun fill_Multi_Liste (TheListe, listSR1R1, column, line, type) = if listSR1R1 == nil then 1 else ( fill_Line TheListe hd listSR1R1 column line type; fill_Multi_Liste TheListe tl listSR1R1 column line+1 type; 0 ) ;; /*************************************************************************** Renvoie le login ou le password d'une base de donnees, on specifie l'alias dans odbcAlias, l'info que l'on souhaite reccueillir dans info ("login" ou "password") les valeurs sont recuperees dans usmress.ini format : odbc.odbcAlias.login odbc.odbcAlias.password attention : odbcAlias, infos ne doivent pas contenir les caracteres suivants : ".*?" ****************************************************************************/ fun GetODBCInfos(odbcAlias,info)= hd switchstr strextr _loadressini strcatn "odbc."::odbcAlias::"."::info::nil ;; /*Initialise the DBACCESSLISTE with READ & WRITE*/ fun InitAccessListe(len) = if len <= 0 then nil else 0::(InitAccessListe len-1) ;; fun fill_combo(combo, list, ind)= if list == nil then 0 else ( fill_combo (_ADDcombo combo 1 hd hd list ) (tl list) (ind+1); 1 ) ;; /*CallBack for DLGmessagebox DBsuccess*/ fun _dbconnect (msgBox, param, ok) = let param -> [tmpAlias tmpLogin tmpPassword win] in ( set Alias = tmpAlias; set Login = tmpLogin; set Password = tmpPassword; let SqlRequest db "GET_TABLES" nil -> tmp in ( fill_combo comboBox tmp 1; fill_combo comboBoxindTab tmp 1 ); _PAINTcombo _SHOWcombo comboBox WINDOW_UNHIDDEN ) ;; fun _comboTable (combo, param, ind, texte) = _RSTlistTab MultiListe ; let SqlRequest db "GET_COLUMNS" (SQL_NIL texte)::nil -> listATTR in ( set LISTEATTRIBUTSBDD = listATTR; fill_Multi_Liste MultiListe listATTR 0 0 1; fill_Multi_Liste MultiListe MakeAccessListe set ListAccess = InitAccessListe listlength listATTR 3 0 0 ); _SETtext TableTexte strcatn (_locEditor "DB_TABLE" nil)::" "::table::nil ;; fun _comboMetaTable (combo, param, ind, texte) = _RSTcombo comboBoxindAttr; let SqlRequest db "GET_COLUMNS" (SQL_NIL texte)::nil -> listMETAATTR in fill_combo comboBoxindAttr listMETAATTR 1 ;; fun _comboMetaAttrTable (combo, param, ind, texte) = 0 ;; fun new_access_liste (list, listind, value) = if listind == nil then list else new_access_liste (replace_nth_in_list list hd listind value) tl listind value ;; /*Modif DB access : full access */ fun _DbFullAccess (bttn, param) = set ListAccess = new_access_liste ListAccess listsel FULLACCESS; fill_Multi_Liste MultiListe MakeAccessListe ListAccess 3 0 0 ;; /*Modif DB access : Read Only access */ fun _DbReadAccess (bttn, param) = set ListAccess = new_access_liste ListAccess listsel READONLY; fill_Multi_Liste MultiListe MakeAccessListe ListAccess 3 0 0 ;; /*Modif DB access : No access */ fun _DbNoAccess (bttn, param) = set ListAccess = new_access_liste ListAccess listsel NOACCESS; fill_Multi_Liste MultiListe MakeAccessListe ListAccess 3 0 0 ;; fun icomp( i1, i2) = i1==i2 ;; fun cherche (list, cle) = if list == nil then 0 else if (hd list) == cle then 1 else cherche tl list cle ;; /*Primary Key*/ fun _DbKey (bttn, param) = if (cherche ListAccess KEY) == 1 then ( _DLGMessageBox _channel EditorWin (_locEditor "KEY_TITLE" nil) (_locEditor "KEY_MESSAGE" nil) 0; 0 ) else if (listlength listsel) != 1 then ( _DLGMessageBox _channel EditorWin (_locEditor "KEY_TITLE" nil) (_locEditor "KEY_MESSAGE" nil) 0; 0 ) else ( set ListAccess = new_access_liste ListAccess listsel KEY; fill_Multi_Liste MultiListe MakeAccessListe ListAccess 3 0 0; 1 ) ;; fun cbSave (filename, n)= let _GETcombo comboBox -> [_ table] in let _GETcombo comboBoxindTab -> [_ MetaTable] in let _GETcombo comboBoxindAttr -> [_ MetaTableAttr] in let _GETtext AliasEditTexte -> AliasDB in let itoa _GETcheck check -> tmp in ("action":: "start" ::nil):: ("action":: "refreshfromDB" ::nil):: ("actionC":: "show" ::nil):: ("actionC":: "hide" ::nil):: ("event":: "out" ::nil):: ("event":: "entering" ::nil):: ("eventC":: "querySQL" ::nil):: ("eventC":: "refresh" ::nil):: ("eventC":: "shown" ::nil):: ("eventC":: "hidden" ::nil):: ("eventC":: "in" ::nil):: ("insert":: tmp ::nil):: ("alias":: AliasDB ::nil):: ("table":: table ::nil):: ("MetaTable":: MetaTable ::nil):: ("MetaTableAttr":: MetaTableAttr ::nil):: ("accessList"::(strbuild convertIR1TOSR1R1 ListAccess)::nil):: nil ;; fun _check (objet, param, state) = if state == 1 then ( _ENcombo comboBoxindTab 0; _ENcombo comboBoxindAttr 0 ) else ( _ENcombo comboBoxindTab 1; _ENcombo comboBoxindAttr 1 ) ;; fun ISELEMINSR1R1 (elem, SR1R1, ind) = if SR1R1 == nil then nil else let hd hd SR1R1 -> tmpELEM in let _fooS strcatn "les deux éléments sont identiques ??? : "::elem::" "::tmpELEM::nil -> _ in if !strcmp elem tmpELEM then ( ind ) else ( ISELEMINSR1R1 elem tl SR1R1 ind+1 ) ;; fun UpDateAccessListe (listATTRNEW, listATTROLD, listACCES) = if listATTRNEW ==nil then nil else let hd hd listATTRNEW -> NewElem in let _fooS strcatn "NewElem = "::NewElem::nil -> _ in let ISELEMINSR1R1 NewElem listATTROLD 0 -> value in let _fooS strcatn "Valeur de l'index = "::(itoa value)::nil -> _ in if value == nil then 0::(UpDateAccessListe tl listATTRNEW listATTROLD listACCES) else (nth_list listACCES value)::(UpDateAccessListe tl listATTRNEW listATTROLD listACCES) ;; fun connectionDB (aliasDB, loginDB, pwdDB)= let if aliasDB ==nil then "" else aliasDB -> al in let if loginDB ==nil then "" else loginDB -> lo in let if pwdDB ==nil then "" else pwdDB -> pwd in let SqlCreate _channel al lo pwd -> dbtmp in if db == nil then ( set db = dbtmp; _DLGrflmessage _DLGMessageBox _channel EditorWin (_locEditor "WINDOW_NAME_DBCONNECT" nil) (_locEditor "DBCONNECT_SUCCESS" nil) 0 @_dbconnect [al lo pwd EditorWin]; 0 ) else /*Il y a déjŕ une base*/ ( let _GETcombo comboBox -> [_ table] in let SqlRequest dbtmp "GET_TABLES" nil -> sqlreq in if (IsThisTableExist table sqlreq) == 1 then (/*The last table exist in the new DataBase*/ let SqlRequest dbtmp "GET_COLUMNS" (SQL_NIL table)::nil -> listATTR in ( _RSTlistTab MultiListe; fill_Multi_Liste MultiListe listATTR 0 0 1; _fooS "\n\n\n\n\n\nmessage de DEGUB debut µµµµ ::: \n\n"; _fooIList ListAccess; _fooS "\n\n\n\n\n\nmessage de DEGUB FIN \n\n"; _fooS strcat "Liste ancienne version = " strbuild LISTEATTRIBUTSBDD; let UpDateAccessListe listATTR LISTEATTRIBUTSBDD ListAccess -> tmpListAcces in /* set LISTEATTRIBUTSBDD = listATTR */ ( set ListAccess = tmpListAcces; _fooS "\n\n\n\n\n\nmessage de DEGUB debut µµµµ ::: \n\n"; _fooIList ListAccess; _fooS "\n\n\n\n\n\nmessage de DEGUB FIN \n\n"; fill_Multi_Liste MultiListe MakeAccessListe ListAccess 3 0 0; ) ); ) else (/*The Last Table doesnt exist in the new DataBase*/ /*set dbSource = dbtmp;*/ _DLGrflmessage _DLGMessageBox _channel EditorWin (_locEditor "WINDOW_NAME_DBCONNECT" nil) (_locEditor "DBCONNECT_SUCCESS" nil) 0 @_dbconnect [al lo pwd EditorWin]; 0 ) ) /* if dbtmp != nil then /*DB success*/ ( set db = dbtmp; _DLGrflmessage _DLGMessageBox _channel EditorWin (_locEditor "WINDOW_NAME_DBCONNECT" nil) (_locEditor "DBCONNECT_SUCCESS" nil) 0 @_dbconnect [al lo pwd EditorWin]; 0 ) else /*DB failed*/ ( _DLGMessageBox _channel EditorWin (_locEditor "WINDOW_NAME_DBCONNECT" nil) (_locEditor "DBCONNECT_FAILURE" nil) 0; 0 ) */ ;; fun cbConnect (btn, param) = let _GETtext param -> tmpAlias in let GetODBCInfos tmpAlias "login" -> tmpLogin in let GetODBCInfos tmpAlias "password" -> tmpPwd in connectionDB tmpAlias tmpLogin tmpPwd ;; fun _OdbcOk(Otext, param, truc)= let _GETtext Otext -> tmpAlias in let GetODBCInfos tmpAlias "login" -> tmpLogin in let GetODBCInfos tmpAlias "password" -> tmpPwd in connectionDB tmpAlias tmpLogin tmpPwd ;; fun cbLoad(list)= if firstuse == 0 then ( set firstuse= firstuse+1; _RSTlistTab MultiListe ; set db = nil; _SETtext AliasEditTexte set Alias = (getInfo list "alias"); set Login= GetODBCInfos Alias "login"; set Password = GetODBCInfos Alias "password"; set table = hd hd strextr (getInfo list "table"); set MetaTable = hd hd strextr (getInfo list "MetaTable"); set MetaTableAttr = hd hd strextr (getInfo list "MetaTableAttr"); set ListAccess = convertSR1R1TOIR1 strextr (getInfo list "accessList"); _SETcheck check atoi hd hd strextr (getInfo list "insert"); _check check nil atoi hd hd strextr (getInfo list "insert"); /* if Alias==nil && Login == nil && Password==nil && table == nil then */ if Alias==nil then 0 else ( let SqlCreate _channel Alias (if !strcmp Login nil then "" else Login) (if !strcmp Password nil then "" else Password) -> dbtmp in if dbtmp != nil then /*DB success*/ ( set db = dbtmp; let SqlRequest db "GET_TABLES" nil -> tmp in ( fill_combo comboBox tmp 1; fill_combo comboBoxindTab tmp 1 ); 0 ) else /*DB failed*/ ( _DLGMessageBox _channel EditorWin (_locEditor "WINDOW_NAME_DBCONNECT" nil) (_locEditor "DBCONNECT_FAILURE" nil) 0; 0 ); let SqlRequest db "GET_COLUMNS" (SQL_NIL table)::nil -> listATTR in let SqlRequest db "GET_COLUMNS" (SQL_NIL MetaTable)::nil -> listMETAATTR in ( set LISTEATTRIBUTSBDD = listATTR; _SETtext AliasTexte strcatn (_locEditor "DB_ALIAS" nil)::" "::Alias::nil; fill_combo comboBoxindAttr listMETAATTR 1; _SSELcombo comboBox table; _SSELcombo comboBoxindTab MetaTable; _SSELcombo comboBoxindAttr MetaTableAttr; fill_Multi_Liste MultiListe listATTR 0 0 1; fill_Multi_Liste MultiListe MakeAccessListe ListAccess 3 0 0 ) ) ) else 0 ;; fun multi_select ( list, int) = if is_in_list list int then removef_from_list list @icomp int else int::list ;; fun addSel (ind, list) = if is_in_list list ind then list else ind::list ;; fun shiftSelMaj (deb, fin, list) = if deb > fin then list else shiftSelMaj deb+1 fin addSel deb list ;; fun shiftSelInf (deb, fin, list) = if deb < fin then list else shiftSelInf deb-1 fin addSel deb list ;; fun _SelectMListe (Liste, param, i1) = _ENbutton NoAccessBttn 1; _ENbutton FullAccessBttn 1; _ENbutton ReadAccessBttn 1; _ENbutton PrimariKeyBttn 1; set listsel = if i1 != -1 then /*Control*/ if _keybdstate == 2 then multi_select listsel i1 else /*Shift*/ if _keybdstate == 1 then ( let hd listsel -> lastone in ( set listsel = nil; if lastone <= i1 then shiftSelMaj lastone i1 listsel else shiftSelInf lastone i1 listsel ) ) else i1::nil else nil ;; fun _ReSizeEditor ( win, param, width, height ) = let width -> Wt in let height -> Ht in let 10 -> step in let 20 -> Tstep in let 50 -> Lbtn in let (Wt/2)-3*step/2-Lbtn -> endlabel in let Wt-2*step -> Llist in let Ht-5*step-5*Tstep -> Hlist in let 80 -> endlabelTable in ( /*DB alias*/ _SIZEtext AliasTexte 100 2*Tstep step step+5; _SIZEtext AliasEditTexte Wt/2-(2*step+175) Tstep step+100 step+10; _SIZEbutton ConnectBtn 70 Tstep step+90+ Wt/2-(2*step+160) step+10; /*Label for Table :*/ _SIZEtext TableTexte Lbtn Tstep 2*step+endlabel+Lbtn step+Tstep/2; _SIZEbutton OdbcModifButtn Lbtn Tstep step+endlabel step+Tstep/2; /*_SIZEbutton TableModifButtn Lbtn Tstep 2*step+2*endlabel+Lbtn step+Tstep/2;*/ _SIZEcombo comboBox width-(2*step+endlabel+2*Lbtn)-step 500 2*step+endlabel+2*Lbtn step+Tstep/2; _SIZElistTab MultiListe Llist Hlist step 2*step+2*Tstep; let Ht-step-Tstep -> ybottom in let (Wt-5*step-2*Lbtn)/2 -> Lcombo in ( _SIZEcheck check 400 Tstep step ybottom-Tstep ; _SIZEtext labelMetaTable Lbtn Tstep step ybottom; _SIZEtext labelMetaInd Lbtn Tstep 3*step+Lbtn+Lcombo ybottom; _SIZEcombo comboBoxindTab Lcombo 100 2*step+Lbtn ybottom; _SIZEcombo comboBoxindAttr Lcombo 100 4*step+2*Lbtn+Lcombo ybottom ); let Ht-2*step-3*Tstep -> Ystart in let 100 -> LargeLbtn in ( _SIZEbutton FullAccessBttn LargeLbtn Tstep step Ystart; _SIZEbutton ReadAccessBttn LargeLbtn Tstep 2*step+LargeLbtn Ystart; _SIZEbutton NoAccessBttn LargeLbtn Tstep 3*step+2*LargeLbtn Ystart; _SIZEbutton PrimariKeyBttn LargeLbtn Tstep 4*step+3*LargeLbtn Ystart ) ) ;; fun cbPro () = let BigToAsc BigInvn BigFromAsc _getpack _checkpack "dms/db/dbeditor/dbeditor.conf" BigFromAsc "c8aa22856afe3a01" -> s in let if (strlen s)!=9 then nil else [htoi substr s 1 4 htoi substr s 5 4] -> [datedebut periode] in if periode==nil then (_DLGMessageBox _channel nil _locEditor "PRO_WARNING" nil _locEditor "PRO_INVALID_MSG" nil 0;0) else if periode==0 then 1 else let ((time>>1)&0x3fffffff)/43200-datedebut -> x in if x<0 then (_DLGMessageBox _channel nil _locEditor "PRO_WARNING" nil _locEditor "PRO_INVALID_MSG" nil 0;0) else if x<=periode then (_DLGMessageBox _channel nil _locEditor "PRO_WARNING" nil _locEditor "PRO_LIMITED_MSG" (itoa (periode-x))::nil 0;1) else (_DLGMessageBox _channel nil _locEditor "PRO_WARNING" nil _locEditor "PRO_ENDLIMITED_MSG" nil 0;0) ;; fun CreateApi(filename)= set font = _CRfont _channel 14 0 FF_WEIGHT "Arial"; set ed = _StartEditor _channel nil 0 0 640 480 WN_NORMAL EDITOR_NORMAL @cbLoad @cbSave @cbPro; set EditorWin = getEditWin ed ; let _GETwindowSizePosition EditorWin -> [Wt Ht _ _] in let 10 -> step in let 20 -> Tstep in let 50 -> Lbtn in let (Wt/2)-3*step/2-Lbtn -> endlabel in let Wt-2*step -> Llist in let Ht-5*step-5*Tstep -> Hlist in ( /*DB alias*/ set AliasTexte = _CRtext _channel EditorWin step step+5 100 2*Tstep ET_ALIGN_LEFT (_locEditor "DB_ALIAS" nil); set AliasEditTexte = _CReditLine _channel EditorWin step+100 step+10 Wt/2-(2*step+175) Tstep ET_BORDER|ET_TABFOCUS|ET_AHSCROLL ""; _CBlineOk AliasEditTexte @_OdbcOk []; set ConnectBtn = _CRbutton _channel EditorWin step+90+ Wt/2-(2*step+160) step+10 70 Tstep 0 (_locEditor "DB_CONECTION" nil); _CBbutton ConnectBtn @cbConnect AliasEditTexte; /*Label for Table :*/ set TableTexte = _CRtext _channel EditorWin 2*step+endlabel+Lbtn step+Tstep/2 Lbtn Tstep*2 ET_ALIGN_LEFT (_locEditor "DB_TABLE" nil); /*Modif DB Table*/ set comboBox = _CBcombo _CRcombo _channel EditorWin 2*step+endlabel+2*Lbtn step+Tstep/2 Wt-(2*step+endlabel+2*Lbtn)-step 500 CB_NOEDIT|CB_AHSCROLL|CB_DOWN "" @_comboTable nil; let Ht-step-Tstep -> ybottom in let (Wt-5*step-2*Lbtn)/2 -> Lcombo in ( /*Label et combo pour récéption de la Méta table*/ set check = _SETcheck _CBcheck _CRcheck _channel EditorWin step ybottom-Tstep 400 Tstep 0 (_locEditor "DB_INSERTMETATABLE" nil) @_check nil 1; set labelMetaTable = _CRtext _channel EditorWin step ybottom Lbtn Tstep ET_ALIGN_LEFT (_locEditor "DB_INDTABLE" nil); set comboBoxindTab = _ENcombo _CBcombo _CRcombo _channel EditorWin 2*step+Lbtn ybottom Lcombo 100 CB_NOEDIT|CB_AHSCROLL|CB_DOWN "" @_comboMetaTable nil 0; /*Label et combo pout récéption de l'attribut Max id*/ set labelMetaInd = _CRtext _channel EditorWin 3*step+Lbtn+Lcombo ybottom Lbtn Tstep ET_ALIGN_LEFT (_locEditor "DB_INDATTR" nil); set comboBoxindAttr = _ENcombo _CBcombo _CRcombo _channel EditorWin 4*step+2*Lbtn+Lcombo ybottom Lcombo 100 CB_NOEDIT|CB_AHSCROLL|CB_DOWN "" @_comboMetaAttrTable nil 0 ); /* set TableModifButtn = _CBbutton _CRbutton _channel EditorWin 2*step+2*endlabel+Lbtn step+Tstep/2 Lbtn Tstep nil (_locEditor "DB_MODIF" nil) @_buttnModifTable nil;*/ /*Multi_Liste des attributs*/ set MultiListe = _CRlistTab _channel EditorWin step 2*step+2*Tstep Llist Hlist LV_BORDER; _ADDlistTabColumn MultiListe 0 100 ET_ALIGN_LEFT (_locEditor "ATTR_NAME" nil); _ADDlistTabColumn MultiListe 1 100 ET_ALIGN_LEFT (_locEditor "ATTR_TYPE" nil); _ADDlistTabColumn MultiListe 2 100 ET_ALIGN_LEFT (_locEditor "ATTR_WIDTH" nil); _ADDlistTabColumn MultiListe 3 100 ET_ALIGN_LEFT (_locEditor "ATTR_USE" nil); _CBlistTabSelect MultiListe @_SelectMListe nil ; /* _CBlistTabRSelect MultiListe @_RSelectMListe nil ;*/ let Ht-2*step-3*Tstep -> Ystart in let 100 -> LargeLbtn in ( /*Full DB access*/ set FullAccessBttn = _ENbutton _CBbutton _CRbutton _channel EditorWin step Ystart LargeLbtn Tstep nil (_locEditor "DB_FULLACCESS" nil) @_DbFullAccess nil 0; /*Read DB Access*/ set ReadAccessBttn = _ENbutton _CBbutton _CRbutton _channel EditorWin 2*step+LargeLbtn Ystart LargeLbtn Tstep nil (_locEditor "DB_READONLY" nil) @_DbReadAccess nil 0; /*NO DB Access*/ set NoAccessBttn = _ENbutton _CBbutton _CRbutton _channel EditorWin 3*step+2*LargeLbtn Ystart LargeLbtn Tstep nil (_locEditor "DB_NOACCESS" nil) @_DbNoAccess nil 0; set PrimariKeyBttn = _ENbutton _CBbutton _CRbutton _channel EditorWin 4*step+3*LargeLbtn Ystart LargeLbtn Tstep nil (_locEditor "DB_KEY" nil) @_DbKey nil 0 ) ); _CBwinSize EditorWin @_ReSizeEditor nil; _PAINTwindow _SHOWwindow EditorWin WINDOW_UNHIDDEN ;; fun IniEditor(filename)= CreateApi filename; if filename==nil then nil else openDMI ed; 0;;