//AB/ Project WinSock Client
//AB/ Object oIDE_Project is a MdiFrame_Project
  //AB/ Set ProjectName to "WinSock Client"
  //AB/ Set ProjectFileName to "WS_Client.src"
  //AB/ Set Size to 285 310

//AB-IgnoreStart
Use DfAllEnt.pkg
#REPLACE CURRENT$WORKSPACE   "Antwise.Test.Winsock"

// Project Object Structure
//   oMain is a Basicpanel
//     oContainer is a Container3d
//       oMessage is a Form
//       oRecieved is a Edit
//       oSend is a Button
//       oWinsock is a cComWinsock
//       oConnect is a Button
//       oRemoteHostIP is a Form
//       oRemoteHostPort is a Form
//       oLocalHostIP is a Form
//       oStatusForm is a Form
//       oStatusBmp is a BitmapContainer
//     oCloseButton is a Button

// Register all objects
Register_Object oCloseButton
Register_Object oConnect
Register_Object oContainer
Register_Object oLocalHostIP
Register_Object oMain
Register_Object oMessage
Register_Object oRecieved
Register_Object oRemoteHostIP
Register_Object oRemoteHostPort
Register_Object oSend
Register_Object oStatusBmp
Register_Object oStatusForm
Register_Object oWinsock
//AB-IgnoreEnd


//AB-StoreTopStart
//Use cApplicationQ.pkg

// Tested on VDF9.1
// This application also contains parts of:
// - Winsock example by Emil Stojanov, Quantaris, The Netherlands
// - automatic registering of COM controls by Allan Kim Eriksen
// - Winsock ideas from Raveen Ryan Sundram / Mark Hullin from M2
//

// Set date attributes as needed
Set_Date_Attribute SysDate4_State To True
Set_Date_Attribute Date4_State    To True
Set_Date_Attribute Epoch_Value    To 30

//External_Function WNetGetLastError "WNetGetLastErrorA" MPR.DLL ;
//    Pointer lpdwError ;    // error code
//    Pointer lpstrErrorBuf ;   // error description buffer
//    DWORD   nErrorBufSize ; // size of description buffer
//    Pointer lpstrNameBuf ;    // buffer for provider name
//    DWORD   nNameBufSize ;  // size of provider name buffer
//    Returns Integer

Use dfabout.pkg
Use vWin32fh.pkg

// Pre:  sFileName contains the complete path of the file.
// Post: returns the complete path of the file.
// This function is inspired on function SEQ_ExtractPathFromFileName of Sture Andersen.
Function ExtractFolderName Global String sFileName Returns String
  String sFolderName
  String sFilenameOnly
  String sDirSep // this is "\" for windows, or "/" for unix
  Move (sysconf(SYSCONF_DIR_SEPARATOR)) To sDirSep
  If sDirSep In sFileName Begin
    Move (StringFromRightOfChar(sFileName,sDirSep)) To sFileNameOnly
    Move (Replace(sFileNameOnly,sFileName,"")) To sFoldername
  End  
  Function_Return sFolderName
End_Function // ExtractFolderName
    

Function ApplicationStartupPath Returns String
  Integer iNumChars
  String sFilename
  String sPath

  Move (Repeat(Character(0), 1024)) To sFileName
  Move (GetModuleFileName(0, AddressOf(sFilename), 1024)) To iNumChars
  Get ExtractFolderName (CString(sFileName)) To sPath
  Function_Return sPath
End_Function
    
    
Use Regserver.pkg


// Registers the winsock COM control if required and only if 
// required. It makes the following assumptions.
// - this code is run with VDF9 or higher
// - the winsock com control is located in the same folder as your application
//
Procedure AutoRegisterWinsock
  Boolean bOk
  String  sAppStartupPath
  Get ApplicationStartupPath To sAppStartupPath

  Get RegServer (sAppStartupPath+"MSWINSCK.OCX") REGSERVER_REGISTER; 
          "{248DD896-BB45-11CF-9ABC-0080C7E7B78D}" To bOk 
  
End_Procedure // AutoRegisterWinsock

Send AutoRegisterWinsock
//AB-StoreTopEnd

//AB-IgnoreStart
Use dfPanel.pkg
Use Windows.pkg
Use cComWinsock.pkg
Use dfbitmap.pkg
//AB-IgnoreEnd

Object oMain is a Basicpanel

  //AB-StoreTopStart
  Set Minimize_Icon To True
  Set Maximize_Icon To False
  Set Caption_Bar To True
  Set Border_Style To Border_None
  Set Locate_Mode To Center_On_Screen
  
  //AB-StoreTopEnd

  Set Label to "Winsock: TCP Client "
  Set Location to 6 10
  Set Size to 274 273
  //AB-ToolbarPackage
  Use NoToolbar.pkg  //  Tool-Bar object.
  //AB-End
  
  Object oContainer is a Container3d
    Set Size to 230 259
    Set Location to 5 5
    Object oMessage is a Form
      Set Label to "Message:"
      Set Size to 13 160
      Set Location to 42 50
      Set Label_Col_Offset to 2
      Set Label_Justification_Mode to jMode_Right

      //AB-StoreStart
      On_Key kEnter Send OnClick Of oSend
      //AB-StoreEnd

    End_Object    // oMessage

    Object oRecieved is a Edit

      //AB-StoreTopStart
      Set Enabled_State To False
      //AB-StoreTopEnd

      Set Label to "Recieved:"
      Set Size to 137 197
      Set Location to 60 50
      Set Label_Col_Offset to 2
      Set Label_Justification_Mode to jMode_Right

      //AB-StoreStart
      Procedure DisplayMessage String sMessage
        Integer iLines
        
        Get Line_Count To iLines
        If (Edit_Buffer_Count(Self) = 0) Move 0 To iLines
          
        Set Value Item iLines To sMessage
      End_Procedure // DisplayMessage
      //AB-StoreEnd

    End_Object    // oRecieved

    Object oSend is a Button
      Set Label to "Send"
      Set Size to 14 33
      Set Location to 42 214

      //AB-StoreStart
      Procedure OnClick
        Variant vData
          
        Move (Value(oMessage,0)) To vData
        Send ComSendData Of oWinsock (Network_User_Name(Self)+": "+vData)
        Set Value Of oMessage To ""
      End_Procedure // OnClick
      //AB-StoreEnd

    End_Object    // oSend

    Object oWinsock is a cComWinsock
      //AB-IgnoreStart
      INCLUDE_ACTIVEX_RESOURCE "WS_Client.res" oWinsock
      //AB-IgnoreEnd

      //AB-StoreTopStart
      Property String  psRemoteHostIP   Public "127.0.0.1" // "192.168.0.2"
      Property Integer piRemoteHostPort Public 27015
      //AB-StoreTopEnd

      Set Size to 17 19
      Set Location to 78 18

      //AB-StoreStart
      Procedure OnCreate
          Variant vHost vPort
          Forward Send OnCreate
          
          Get psRemoteHostIP   To vHost
          Get piRemoteHostPort To vPort
          
          Set ComProtocol To OLEsckTCPProtocol
          Send ComConnect vHost vPort
      End_Procedure // OnCreate
        
      // Error occurred
      Procedure OnComError Short llNumber Variant llDescription Integer llScode String llSource String llHelpFile Integer llHelpContext Variant llCancelDisplay
          Send DisplayStatus
      End_Procedure
      
      Procedure OnComDataArrival Integer iBytes
          Variant vData
          Integer iState
      
          Move (Repeat(" ",iBytes)) To vData
      
          Send ComGetData (&vData) nothing nothing
      
        Send DisplayMessage Of oRecieved vData
          Send DisplayStatus
      
          Get ComState To iState
          If (iState=OLEsckClosing) Begin
            Send ComClose 
          End
      End_Procedure // OnComDataArrival
        
        
      // Occurs connect operation is completed
      Procedure OnComConnect
          Send DisplayStatus
      End_Procedure
        
      // Occurs when a remote client is attempting to connect
      Procedure OnComConnectionRequest Integer llrequestID
          Send DisplayStatus
      End_Procedure
        
      // Occurs when the connection has been closed
      Procedure OnComClose
          Send DisplayStatus
      End_Procedure
      //AB-StoreEnd

    End_Object    // oWinsock

    Object oConnect is a Button
      Set Label to "(Re)connect"
      Set Location to 206 197

      //AB-StoreStart
      Procedure OnClick
        Variant vHost vPort
        
        Send ApplyCurrentSettings
        
        Get psRemoteHostIP   Of oWinsock To vHost
        Get piRemoteHostPort Of oWinsock To vPort
          
        Send ComClose Of oWinsock
        Send ComConnect Of oWinsock vHost vPort
        
      End_Procedure // OnClick
      //AB-StoreEnd

    End_Object    // oConnect

    Object oRemoteHostIP is a Form
      Set Label to "Remote Host:"
      Set Size to 13 67
      Set Location to 10 50
      Set Label_Col_Offset to 2
      Set Label_Justification_Mode to jMode_Right
    End_Object    // oRemoteHostIP

    Object oRemoteHostPort is a Form
      Set Label to "Port:"
      Set Size to 13 40
      Set Location to 10 155
      Set Label_Col_Offset to 2
      Set Label_Justification_Mode to jMode_Right
    End_Object    // oRemoteHostPort

    Object oLocalHostIP is a Form
      Set Label to "Local Host:"
      Set Size to 13 67
      Set Location to 25 50
      Set Label_Col_Offset to 2
      Set Label_Justification_Mode to jMode_Right
    End_Object    // oLocalHostIP

    Object oStatusForm is a Form
      Set Label to "Status:"
      Set Size to 13 133
      Set Location to 206 50
      Set Color to clBtnFace
      Set Label_Col_Offset to 2
      Set Label_Justification_Mode to jMode_Right

      //AB-StoreStart
      Procedure DisplayStatus
        Integer iState
        String  sMsg
        Get ComState Of oWinsock To iState
        Case Begin
          Case (iState=OLEsckClosed)
            Send UpdateConnectionStatus Of oStatusBmp
            Move "Closed" To sMsg
            Case Break
          Case (iState=OLEsckOpen)   Move "Open" To sMsg
            Case Break
          Case (iState=OLEsckListening) Move "Listening" To sMsg
            Case Break
          Case (iState=OLEsckConnectionPending) Move "Pending request" To sMsg
            Case Break
          Case (iState=OLEsckResolvingHost)     Move "Resolving remote hostname"  To sMsg
            Case Break
          Case (iState=OLEsckHostResolved)      Move "Resolved remote hostname" To sMsg
            Case Break
          Case (iState=OLEsckConnecting)        Move "Connecting.." To sMsg
            Case Break
          Case (iState=OLEsckConnected)         Move "Connected" To sMsg
            Send UpdateConnectionStatus Of oStatusBmp
            Case Break
          Case (iState=OLEsckClosing)           Move "Closing connection" To sMsg
            Case Break
          Case (iState=OLEsckError)             Move "Error" To sMsg
            Case Break
          Case Else
            Move "Unknown" To sMsg
        Case End
        Set Value Item 0 To sMsg
      End_Procedure // DisplayStatus
      //AB-StoreEnd

    End_Object    // oStatusForm

    Object oStatusBmp is a BitmapContainer
      Set Size to 22 24
      Set Location to 202 -1
      Set Bitmap to "red.bmp"
      Set Border_Style to Border_ClientEdge

      //AB-StoreStart
      Procedure UpdateConnectionStatus
        Integer iState
        Get ComState Of oWinsock To iState
        Case Begin
          Case (iState=OLEsckClosed)
            Set Bitmap To "red.bmp"
            Case Break
          Case (iState=OLEsckConnected)
            Set Bitmap To "green.bmp"
            Case Break
          Case Else
            Set Bitmap To "unknown.bmp"
        Case End
      End_Procedure // UpdateConnectionStatus
      
      //AB-StoreEnd

    End_Object    // oStatusBmp


    //AB-StoreStart
    Procedure ReadCurrentSettings       
      String  sRemoteHostIP
      Integer iRemoteHostPort
      Integer iPort
      String  sIP
      Get psRemoteHostIP   Of oWinsock To sRemoteHostIP
      Get piRemoteHostPort Of oWinsock To iRemoteHostPort
      Get ComLocalIP       Of oWinsock To sIP
      
      Set Value Of (oRemoteHostIP(Self))   To sRemoteHostIP
      Set Value Of (oRemoteHostPort(Self)) To iRemoteHostPort
      Set Value Of (oLocalHostIP(Self))    To sIP
    End_Procedure // ReadCurrentSettings
    
    Procedure ApplyCurrentSettings
      String  sRemoteHostIP
      Integer iRemoteHostPort
      Get Value Of (oRemoteHostIP(Self))   To sRemoteHostIP
      Get Value Of (oRemoteHostPort(Self)) To iRemoteHostPort
      
      Set psRemoteHostIP   Of oWinsock To sRemoteHostIP
      Set piRemoteHostPort Of oWinsock To iRemoteHostPort
    End_Procedure // ApplyCurrentSettings 
    
    Procedure DisplayStatus
      Send DisplayStatus Of (oStatusForm(Self)) 
    End_Procedure // DisplayStatus
    
    Procedure Activating Returns Integer
      Integer iRetVal
      Forward Get msg_activating To iRetval
      If Not (iRetVal) Begin
        Send ReadCurrentSettings
      End
      Procedure_Return iRetVal
    End_Procedure // Activating
    //AB-StoreEnd

  End_Object    // oContainer

  Object oCloseButton is a Button
    Set Label to "&Close"
    Set Location to 238 214

    //AB-StoreStart
    Procedure OnClick
        Send Exit_Application
    End_Procedure  // OnClick
    
    //AB-StoreEnd

  End_Object    // oCloseButton

  //AB-StatusBarPackage
  Use NoStatusbar.pkg  //  Status-Bar object.
  //AB-End
  

  //AB-StoreStart
  On_Key Key_F5 Send DisplayStatus Of (oContainer(Self)) 
  On_Key Key_Alt+Key_C Send KeyAction To (oCloseButton(Self))
  
  //AB-StoreEnd

End_Object    // oMain


//AB-StoreStart
Start_UI (oMain(Self))
//AB-StoreEnd

//AB/ End_Object    // oIDE_Project
