Module Data_set.pkg

     1//************************************************************************
     2//
     3// Confidential Trade Secret.
     4// Copyright 1987-1997 Data Access Corporation, Miami FL, USA
     5// All Rights reserved
     6// DataFlex is a registered trademark of Data Access Corporation.
     7//
     8//************************************************************************/
     9
    10//************************************************************************
    11//     File Name: Data_Set.Pkg
    12// Creation Date: January 1, 1991
    13// Modified Date: April 21, 1992
    14//     Author(s): Steven A. Lowe
    15//
    16// This module contains the Data_Set class definition.
    17//************************************************************************/
    18// 4/21/99   JJT Added OnConstrain support
    19// 11/26/97  JJT Moved data_set_should_save into class from dfclient.pkg
    20// 04/11/97  JJT Added Refind_DD_Records which is just like Refind_records
    21//              except it only operates on in_use DDs. Otherwise, non
    22//              connected not-in-use DDs clear the buffer (very bad for
    23//              sysfiles).
    24// 11/05/96 JJT Added Set DDO_Server Message (same as Attach_Server)
    25// 08/29/96 JJT Item_Find Fix, where send attach_main_File sent to server
    26// 07/23/96 JJT Renamed to DataSet (Maintain Data_Set as well)
    27//************************************************************************/
    28// 2/26/2002  JJT - 8.2 clean up (indirect_file, local, self, etc.)
    29
    30#CHKSUB 2 1  // Verify the data_set subsystem.
    31
    32use VDFBase.pkg
    33use fndmodes.pkg
    34use refmodes.pkg
    35//use enclient.pkg
    36
    37#IFDEF REPLACE_CLASS_NAME
    38#ELSE
    39   #COMMAND REPLACE_CLASS_NAME R R
    40      #IFDEF U_!2
    41          #Replace U_!1 U_!2
    42          #IFSUB '!2$SC'
    43             #Replace !1$SC !2$SC
    44          #ENDIF
    45          #IFSUB '!2$SM'
    46             #Replace !1$SM !2$SM
    47          #ENDIF
    48          #IFSUB '!2$EM'
    49             #Replace !1$EM !2$EM
    50          #ENDIF
    51      #ENDIF
    52   #ENDCOMMAND
    53#ENDIF
    54
    55// removed in 14.1 (These were never used)
    56// Define defaults (If not previously defined)
    57//define DEFAULT$SMART$FILEMODE$STATE for FALSE
    58//define DEFAULT$CASCADE$DELETE$STATE for TRUE
    59
    60//
    61//Global integer status values
    62//
    63define OPERATION_MODE   for |VI99  //status of data-sets in application
    64define OPERATION_ORIGIN for |VI108 //origin of current of data-set operation
    65
    66//
    67//Constants for Operation_Mode global int values
    68//
    69define MODE_WAITING  for 0  //wait-mode
    70define MODE_FINDING  for 1  //find-mode
    71define MODE_CLEARING for 2  //clear-mode
    72define MODE_CREATING for 3  //create-mode
    73define MODE_SAVING   for 4  //save-mode
    74define MODE_DELETING for 5  //delete-mode
    75define MODE_ABORTING for 6  //abort-mode
    76define MODE_VALIDATING for 7  //request_validate-mode : added for VDF7
    77define MODE_CLEARINGALL for 8 //clear-all mode (added in VDF8)
    78
    79//
    80// Description
    81//
    82//   The Data_Set class is implemented as a subclass of Entry_Client, with
    83//   a C language handler providing the majority of new behavior.  The
    84//   Data_Set class is intended to be a grouping agent for data-entry objects
    85//   and a container for subordinate Data_Sets.
    86//
    87// Assumptions/Preconditions
    88//
    89//   None.
    90//
    91// Exceptions
    92//
    93//   None.
    94//
    95// Notes
    96//
    97//  Syntax:
    98//
    99//  Object <name> is a DataSet <image> {ACTION_BAR <ActionBar>} {POP_UP}
   100//      {RING} {MAIN_FILE <Main_File> {BY <Index>} }
   101//      {UPDATING <File> | <DataSetID> ... } }
   102//   :
   103//  End_Object
   104//
   105//  Data_Sets may be used to group DEOs as well as other Data_Sets.
   106//  Note also that a nested (component) Data_Set automatically enforces an
   107//  UPDATES visibility and a RELATES TO constraint between its main_file and
   108//  its parent's main_file.
   109//
   110
   111// _Data_Set class deinition, private class layer. (Extra class layer needed
   112// to augment procedures defined in C class handler.)
   113//
   114// _Data_Set class deinition, private class layer. (Extra class layer needed
   115// to augment procedures defined in C class handler.)
   116//
   117//Class _Data_Set is an Entry_Client ;  //_Data_Set inherits from Entry_Client
   118//    STARTMAC dsStart ;                //dsStart macro is used to handle syntax
   119//    0 0 ;                             //default colors
   120//    Data_Set_Handler                  //C-function for base class behavior
   121
   122//  !A [] $461 U__DATA_SET              //register C messages
   123
   124//#IFDEF IS$WINDOWS
   125Use BaseData_Set.pkg
   126
   127// Data_Set class definition, public class layer. (Extra class layer needed
   128// to augment C-based (Constrain) procedure(s).)
   129
   130{ ClassType=Abstract ClassLibrary=Common }
   131{ HelpTopic=DataSet }
   132Class DataSet is a BaseData_Set
   133
   134
   135   // maintain old name for the time being to maximize compatability
   136   // between character mode and windows versions. Developers should be
   137   // able to move DS classes back and forth without changes.
   138   Replace_Class_Name Data_Set DataSet
   139
   140   Procedure Construct_Object //Integer Img#
   141     Forward Send Construct_Object No_Image //Img#
   142
   143     { DesignTime=False }
   144     Property Integer Constrain_File 0
   145     { Category=Data }
   146     { PropertyType=Boolean }
   147     Property Integer Auto_Fill_State False
   148     { Visibility=Private }
   149     Property Integer Change_Disabled_State  False
   150     // RT sets this inside of Mark_components a part of old entry_client DSO behavior. Now it is never used
   151     { Visibility=Private }
   152     Property Integer Component_State False
   153
   154     // just use RT default of False & True
   155     //Set Smart_Filemode_State to DEFAULT$SMART$FILEMODE$STATE
   156     //Set Cascade_Delete_State to DEFAULT$CASCADE$DELETE$STATE
   157     // Set Focus_Mode to NO_ACTIVATE
   158   End_Procedure  // Construct_Object
   159
   160
   161  //
   162  // This may be called by legacy DSO and DDO code
   163  //
   164  // IMPORTANT NOTE of change for 8.2:
   165  //         DO NOT call or augment this anymore.
   166  //
   167  //         for sending: Find all cases of Field_main_index and change it to File_Field_Index
   168  //
   169  //         for augmenting: In DSOs - replace Field_main_index with File_field_index
   170  //                         In DDOs - replace Field_main_Index with Field_Index and do not pass
   171  //                                   the file parameter.
   172  //                                   See DDOs Field_index and File_field_Index for more
   173  //
   174  { Obsolete=True MethodType=Property }
   175  function Field_Main_Index integer file integer field returns integer
   176    integer dataType fldNdx retval ordr
   177    move -1 to retval      //field has no main index (default)
   178    if file ne 0 begin
   179//      FIELD_DEF file field to dataType fldNdx
   180      get_attribute DF_FIELD_INDEX of file field to fldNdx // main index field
   181      if (fldNdx > 0 OR field = 0) move fldNdx to retval //field has main index
   182    end
   183    if file eq (main_file(self)) begin
   184      get ordering to ordr
   185      if ordr ge 0 move ordr to retval  //ordering takes precedence over main index
   186    end
   187    function_return retval
   188  end_function
   189
   190    // This allows packages that still use data-sets instead of DDOs to use this
   191    // message syntax.
   192    // Note that this will never get here if the DD class is used as
   193    // it has its own handler for this. It only is called if DSOs are used in which
   194    // case it calls the old message field_main_index above.
   195    // DDO based objects will NEVER call this code
   196    //
   197    { Visibility=Private MethodType=Property }
   198    function File_Field_Index integer iFile integer iField returns integer
   199        function_return (Field_main_Index(self,iFile,iField))
   200    end_function
   201
   202
   203  { Visibility=Private }
   204  procedure Item_Find integer eFindMode ;
   205                      integer iFile integer iField ;
   206                      integer bDoEntryUpdate integer bShowFindErr integer bDeferred
   207
   208    RowId   riRow
   209    integer iIndex
   210    Handle  hoServer
   211    integer iSegments iSeg iSegFld iSegFldMainIndex
   212    boolean bChanged bDoCheck bOk
   213
   214    //Get Field_Main_Index iFile iField to iIndex
   215    Get File_Field_Index iFile iField to iIndex
   216    If (iIndex<>-1) Begin
   217      // get prior rowId before it get cleared
   218      Move (GetRowID(iFile)) to riRow
   219      //  'hold' buffer to prepare for entry_update
   220      Set_Attribute DF_FILE_STATUS of iFile to DF_FILE_INACTIVE
   221      if bDoEntryUpdate Begin
   222        send Request_Entry_Update iFile 1  //entUpdt all DEOs as required
   223
   224        // If the buffer is cleared (no record and no changed data) then we want
   225        // to do a constrained_clear which will force the buffer to get cleared
   226        // according to the rules of the current constraints.
   227        //Get_field_value iFile 0 to iRec
   228        //Move (GetRowID(iFile)) to riRow // 12.1 moved above the set file inactive
   229
   230        // If there was an active record to begin with we consider this changed (not cleared)
   231        If (not(IsNullRowId(riRow))) Begin
   232            Move True to bChanged
   233        End
   234        Else Begin
   235            // or, if the record was already changed or the entry_update created a change
   236            // we consider this changed
   237            Get_Attribute DF_FILE_CHANGED of iFile to bChanged
   238        End
   239
   240        If not bChanged Begin
   241            // if buffer is unchanged, do a constrained clear. It is unchanged if there was not
   242            // active record, the record was unchanged, and the update didn't change anything.
   243            Constrained_Clear eFindMode iFile by iIndex
   244        End
   245        Else If (eFindMode=GE or eFindMode=LE and iIndex>0) Begin
   246
   247             // If mode is GE or LE we need to do some extra processing. We want to clear
   248             // all index segemnt fields that occur after this field in the index. This way
   249             // dbList searches and find ge searches (f9) will always find the first record
   250             // that matches the data in the field being searched. This was if an index like
   251             // customer.name x customer.number where you had 10 identical names "john" typing
   252             // john will find the first record, because customer.number will get cleared.
   253             // Note we can no do this with GT or LT or you'd get stuck in fields
   254
   255             // check all fields for index. Once you find the iField field, clear all
   256             // fields that follow it. Only do this if the other fields do not use the
   257             // same index as its primary index (in which case we assume the data is intentional).
   258             // This should handle most cases.
   259             get_attribute DF_INDEX_NUMBER_SEGMENTS of iFile iIndex to iSegments
   260             for iSeg from 1 to iSegments
   261                 get_Attribute DF_INDEX_SEGMENT_FIELD of iFile iIndex iSeg to iSegFld
   262                 If not bDoCheck begin
   263                     If (iSegFld=iField) ;
   264                         Move True to bDoCheck // marked after we find the find field in the index
   265                 end
   266                 else Begin // we get here after we've found the main field segment
   267                    // if main index if this segment is same as our find index, do nothing
   268                    Get File_Field_Index iFile iSegFld to iSegFldMainIndex
   269                    If (iSegFldMainIndex<>iIndex) ;
   270                        set_field_value iFile iSegFld to ''
   271                end
   272             loop
   273        end
   274
   275        Get Which_Data_Set iFile to hoServer
   276        if (hoServer AND iFile=main_file(hoServer)) ;
   277             send Attach_Main_File to hoServer
   278        else ;
   279             attach iFile
   280      end
   281
   282      indicate err false
   283
   284      if (Is_SuperFind_Required(self,iFile)) ;
   285          send Request_SuperFind eFindMode iFile iField
   286      else if bDeferred ;
   287          send Request_Read eFindMode iFile iIndex
   288      else ;
   289          send Request_Find eFindMode iFile iIndex
   290
   291      If (not(found) and not(err)) begin
   292          // refind original record (or leave it cleared if not record)
   293          Move (FindByRowId(iFile,riRow)) to bOk
   294
   295          if bShowFindErr ;
   296              error (if(eFindMode<2, DFERR_FIND_PRIOR_BEG_OF_FILE, DFERR_FIND_PAST_END_OF_FILE))
   297          indicate FOUND FALSE
   298      end
   299    end
   300    else ;
   301        if bShowFindErr error DFERR_FIELD_NOT_INDEXED
   302  end_procedure
   303
   304
   305  // We only care about should_saves of DEOs and not DSOs when
   306  // exiting the app. Create a handler for data set class. We still
   307  // broadcast in case we've got nested deos in the dso (hopefully not).
   308  //
   309  { Visibility=Private }
   310  Function Exit_Application_Check Returns Integer
   311    Integer rVal
   312    BroadCast Get Exit_Application_Check to Rval // check w/ kids
   313    Function_return rVal
   314  End_Function
   315
   316   { Visibility=Private }
   317   Procedure Constrain
   318     Integer iFile
   319     Send OnConstrain
   320     Forward Send Constrain
   321     Get Constrain_File to iFile
   322     If iFile ;
   323        Constrain (Main_file(self)) relates to iFile
   324   End_procedure
   325
   326   { MethodType=Event }
   327   Procedure OnConstrain
   328   End_Procedure
   329
   330   // Less confusing Message for adding Updating servers
   331   //
   332   { MethodType=Property }
   333   { DesignTime=False }
   334   Procedure Set DDO_Server Handle ObjId
   335      Send Attach_Server ObjId
   336   End_Procedure // Set DDO_Server
   337
   338   // This is called when a view takes or retakes the
   339   // focus. If DD not in use, do nothing.
   340   //
   341   { Visibility=Private }
   342   Procedure Refind_DD_Records
   343        if (in_use_state(self)) Send refind_records
   344   end_procedure
   345
   346   // this returns true if the data-set is changed AND there are attached
   347   // DEO objects. Without this you can get "changes exist" condition reported
   348   // that the user will have no way of saving.
   349   //
   350   { Visibility=Private MethodType=Property }
   351   Function Data_Set_Should_Save returns integer
   352        Function_Return (Should_Save(self) AND ;
   353                           Data_Set_User_interface_count(self))
   354   End_Function
   355
   356   // returns 0 indicating that this is not DD enabled. DataDictionary objects will return 1.
   357   // Add DSOs and DDOs must understand this message
   358
   359   { MethodType=Property Visibility=Private }
   360   Function Extended_DSO_State Returns Integer
   361       Function_return 0
   362   End_Function // Extended_DSO_State
   363
   364
   365end_class
   366
   367//#COMMAND bind_main_file // this should not be used anymore
   368//  #IF (!0>1)
   369//    #IFSAME !1 MAIN_FILE
   370//      #IFDEF !2.RECNUM
   371//        #PUSH !u
   372//        #SET U$ !2.RECNUM
   373//        set main_file to |CI!u
   374//        #POP u$
   375//      #ELSE
   376//        #ERROR DFERR_COMPILE If !2 is a file it is unopened
   377//      #ENDIF
   378//    #ELSE
   379//      bind_main_file !2 !3 !4 !5 !6 !7 !8 !9
   380//    #ENDIF
   381//  #ENDIF
   382//#ENDCOMMAND
   383
   384//#COMMAND bind_index
   385//  #IF (!0>1)
   386//    #IFSAME !1 BY
   387//      set ordering to !2
   388//    #ELSE
   389//      bind_index !2 !3 !4 !5 !6 !7 !8 !9
   390//    #ENDIF
   391//  #ENDIF
   392//#ENDCOMMAND
   393
   394//#COMMAND Bind_Updating
   395//  #IF (!0>1)
   396//    #IFSAME !1 UPDATING
   397//      SetDependents !2 !3 !4 !5 !6 !7 !8 !9
   398//    #ELSE
   399//      Bind_Updating !2 !3 !4 !5 !6 !7 !8 !9
   400//    #ENDIF
   401//  #ENDIF
   402//#ENDCOMMAND
   403
   404//#COMMAND SetDependents   //<File>|<Server#> [ ... ] ...obsolete
   405//  #IF (!0>0)
   406//    #IFDEF !1
   407//      send Attach_Server !1
   408//    #ELSE
   409//      #IFDEF !1.OBJ
   410//        send attach_Server !1.OBJ
   411//      #ELSE
   412//        #IFDEF !1.RECNUM
   413//          #PUSH !u
   414//          #SET U$ !1.RECNUM
   415//          send Add_Parent_File |CI!u
   416//          #POP U$
   417//        #ELSE
   418//          #ERROR DFERR_COMPILE If !1 is a file it is unopened
   419//        #ENDIF
   420//      #ENDIF
   421//    #ENDIF
   422//    SetDependents !2 !3 !4 !5 !6 !7 !8 !9
   423//  #ENDIF
   424//#ENDCOMMAND
   425
   426#COMMAND BEGIN_CONSTRAINTS
   427  procedure Constrain
   428#ENDCOMMAND
   429
   430#COMMAND END_CONSTRAINTS
   431    forward send constrain
   432  end_procedure
   433#ENDCOMMAND
   434