diff --git a/include/wx/os2/brush.h b/include/wx/os2/brush.h index a0a1bd7471..6861816ec8 100644 --- a/include/wx/os2/brush.h +++ b/include/wx/os2/brush.h @@ -34,10 +34,7 @@ protected: int m_style; wxBitmap m_stipple ; wxColour m_colour; - -/* TODO: implementation WXHBRUSH m_hBrush; -*/ }; #define M_BRUSHDATA ((wxBrushRefData *)m_refData) @@ -74,6 +71,10 @@ public: // Useful helper: create the brush resource bool RealizeResource(); + WXHANDLE GetResourceHandle(void) ; + bool FreeResource(bool force = FALSE); + bool IsFree() const; + // When setting properties, we must make sure we're not changing // another object void Unshare(); diff --git a/include/wx/os2/gsockos2.h b/include/wx/os2/gsockos2.h new file mode 100644 index 0000000000..e70cd06094 --- /dev/null +++ b/include/wx/os2/gsockos2.h @@ -0,0 +1,105 @@ +/* ------------------------------------------------------------------------- + * Project: GSocket (Generic Socket) for WX + * Name: gsockos2.h + * Purpose: GSocket OS/2 header + * CVSID: $Id$ + * ------------------------------------------------------------------------- + */ + +#ifndef __GSOCK_OS2_H +#define __GSOCK_OS2_H + +#ifndef __GSOCKET_STANDALONE__ +#include "wx/setup.h" +#endif + +#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) + +#ifndef __GSOCKET_STANDALONE__ +#include "wx/gsocket.h" +#else +#include "gsocket.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define SIGPIPE 13 + +/* Definition of GSocket */ +struct _GSocket +{ + int m_fd; + GAddress *m_local; + GAddress *m_peer; + GSocketError m_error; + + bool m_non_blocking; + bool m_server; + bool m_stream; + bool m_oriented; + bool m_establishing; + unsigned long m_timeout; + + /* Callbacks */ + GSocketEventFlags m_detected; + GSocketCallback m_cbacks[GSOCK_MAX_EVENT]; + char *m_data[GSOCK_MAX_EVENT]; + + char *m_gui_dependent; +}; + +/* Definition of GAddress */ +struct _GAddress +{ + struct sockaddr *m_addr; + size_t m_len; + + GAddressType m_family; + int m_realfamily; + + GSocketError m_error; +}; + +/* Input / Output */ + +GSocketError _GSocket_Input_Timeout(GSocket *socket); +GSocketError _GSocket_Output_Timeout(GSocket *socket); +int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size); +int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size); +int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size); +int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size); + +/* Callbacks */ + +void _GSocket_Enable(GSocket *socket, GSocketEvent event); +void _GSocket_Disable(GSocket *socket, GSocketEvent event); +void _GSocket_Detected_Read(GSocket *socket); +void _GSocket_Detected_Write(GSocket *socket); + +void _GSocket_GUI_Init(GSocket *socket); +void _GSocket_GUI_Destroy(GSocket *socket); +void _GSocket_Enable_Events(GSocket *socket); +void _GSocket_Disable_Events(GSocket *socket); +void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event); +void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event); + +/* GAddress */ + +GSocketError _GAddress_translate_from(GAddress *address, + struct sockaddr *addr, int len); +GSocketError _GAddress_translate_to(GAddress *address, + struct sockaddr **addr, int *len); + +GSocketError _GAddress_Init_INET(GAddress *address); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */ + +#endif /* __GSOCK_UNX_H */ + diff --git a/include/wx/os2/helpxxxx.h b/include/wx/os2/helpwin.h similarity index 65% rename from include/wx/os2/helpxxxx.h rename to include/wx/os2/helpwin.h index d53c28b7e4..4b52caf81b 100644 --- a/include/wx/os2/helpxxxx.h +++ b/include/wx/os2/helpwin.h @@ -1,33 +1,28 @@ ///////////////////////////////////////////////////////////////////////////// // Name: helpxxxx.h -// Purpose: Help system: native implementation for your system. Replace -// XXXX with suitable name. -// Author: AUTHOR +// Purpose: Help system: native implementation for your system. +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR +// Copyright: (c) David Webster // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifndef _WX_HELPXXXX_H_ -#define _WX_HELPXXXX_H_ - -#ifdef __GNUG__ -#pragma interface "helpxxxx.h" -#endif +#ifndef _WX_HELPWIN_H_ +#define _WX_HELPWIN_H_ #include "wx/wx.h" #include "wx/helpbase.h" -class WXDLLEXPORT wxXXXXHelpController: public wxHelpControllerBase +class WXDLLEXPORT wxWinHelpController: public wxHelpControllerBase { - DECLARE_CLASS(wxXXXXHelpController) + DECLARE_CLASS(wxWinHelpController) public: - wxXXXXHelpController(); - ~wxXXXXHelpController(); + wxWinHelpController(); + ~wxWinHelpController(); // Must call this to set the filename and server name virtual bool Initialize(const wxString& file); @@ -46,7 +41,10 @@ class WXDLLEXPORT wxXXXXHelpController: public wxHelpControllerBase protected: wxString m_helpFile; +private: + // virtual function hiding supression :: do not use + bool Initialize(const wxString& file, int WXUNUSED(server) ) { return(Initialize(file)); } }; #endif - // _WX_HELPXXXX_H_ + // _WX_HELPWIN_H_ diff --git a/include/wx/os2/icon.h b/include/wx/os2/icon.h index 3e0c24729c..07a1f4fb55 100644 --- a/include/wx/os2/icon.h +++ b/include/wx/os2/icon.h @@ -1,21 +1,17 @@ ///////////////////////////////////////////////////////////////////////////// // Name: icon.h // Purpose: wxIcon class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_ICON_H_ #define _WX_ICON_H_ -#ifdef __GNUG__ -#pragma interface "icon.h" -#endif - #include "wx/bitmap.h" class WXDLLEXPORT wxIconRefData: public wxBitmapRefData @@ -27,9 +23,7 @@ public: ~wxIconRefData(); public: -/* TODO: whatever your actual icon handle is - WXHICON m_hIcon; -*/ + WXHICON m_hIcon; }; #define M_ICONDATA ((wxIconRefData *)m_refData) @@ -58,12 +52,9 @@ public: inline bool operator == (const wxIcon& icon) { return m_refData == icon.m_refData; } inline bool operator != (const wxIcon& icon) { return m_refData != icon.m_refData; } -/* TODO: implementation void SetHICON(WXHICON ico); inline WXHICON GetHICON() const { return (M_ICONDATA ? M_ICONDATA->m_hIcon : 0); } -*/ -/* TODO */ virtual bool Ok() const { return (m_refData != NULL) ; } private: // supress virtual function hiding warning @@ -73,7 +64,7 @@ private: { return(wxBitmap::LoadFile(name, type)); }; }; -/* Example handlers. TODO: write your own handlers for relevant types. +// Example handlers. TODO: write your own handlers for relevant types. class WXDLLEXPORT wxICOFileHandler: public wxBitmapHandler { @@ -81,9 +72,9 @@ class WXDLLEXPORT wxICOFileHandler: public wxBitmapHandler public: inline wxICOFileHandler() { - m_name = "ICO icon file"; - m_extension = "ico"; - m_type = wxBITMAP_TYPE_ICO; + m_name = "ICO icon file"; + m_extension = "ico"; + m_type = wxBITMAP_TYPE_ICO; }; virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, @@ -96,9 +87,9 @@ class WXDLLEXPORT wxICOResourceHandler: public wxBitmapHandler public: inline wxICOResourceHandler() { - m_name = "ICO resource"; - m_extension = "ico"; - m_type = wxBITMAP_TYPE_ICO_RESOURCE; + m_name = "ICO resource"; + m_extension = "ico"; + m_type = wxBITMAP_TYPE_ICO_RESOURCE; }; virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, @@ -106,7 +97,6 @@ public: }; -*/ - #endif // _WX_ICON_H_ + diff --git a/include/wx/os2/imaglist.h b/include/wx/os2/imaglist.h index 7e66ffb36a..5dd12e9940 100644 --- a/include/wx/os2/imaglist.h +++ b/include/wx/os2/imaglist.h @@ -3,21 +3,17 @@ // Purpose: wxImageList class. Note: if your GUI doesn't have // an image list equivalent, you can use the generic class // in src/generic. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_IMAGLIST_H_ #define _WX_IMAGLIST_H_ -#ifdef __GNUG__ -#pragma interface "imaglist.h" -#endif - #include "wx/bitmap.h" /* @@ -100,13 +96,6 @@ class WXDLLEXPORT wxImageList: public wxObject // 'bitmap' and 'mask' after calling Replace. bool Replace(int index, const wxBitmap& bitmap, const wxBitmap& mask = wxNullBitmap); -/* Not supported by Win95 - // Replacing a bitmap, using the specified colour to create the mask bitmap - // Note that wxImageList creates new bitmaps, so you may delete - // 'bitmap'. - bool Replace(int index, const wxBitmap& bitmap, const wxColour& maskColour); -*/ - // Replaces a bitmap and mask from an icon. // You can delete 'icon' after calling Replace. bool Replace(int index, const wxIcon& icon); @@ -128,7 +117,6 @@ class WXDLLEXPORT wxImageList: public wxObject wxIcon *MakeIcon(int index); */ -/* TODO // Implementation //////////////////////////////////////////////////////////////////////////// @@ -137,8 +125,6 @@ class WXDLLEXPORT wxImageList: public wxObject protected: WXHIMAGELIST m_hImageList; -*/ - }; #endif diff --git a/include/wx/os2/iniconf.h b/include/wx/os2/iniconf.h new file mode 100644 index 0000000000..28c7436509 --- /dev/null +++ b/include/wx/os2/iniconf.h @@ -0,0 +1,119 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: include/wx/msw/iniconf.h +// Purpose: INI-file based wxConfigBase implementation +// Author: David Webster +// Modified by: +// Created: 10/09/99 +// Copyright: David Webster +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _INICONF_H +#define _INICONF_H + +// ---------------------------------------------------------------------------- +// wxIniConfig is a wxConfig implementation which uses MS Windows INI files to +// store the data. Because INI files don't really support arbitrary nesting of +// groups, we do the following: +// (1) in win.ini file we store all entries in the [vendor] section and +// the value group1/group2/key is mapped to the value group1_group2_key +// in this section, i.e. all path separators are replaced with underscore +// (2) in appname.ini file we map group1/group2/group3/key to the entry +// group2_group3_key in [group1] +// +// Of course, it might lead to indesirable results if '_' is also used in key +// names (i.e. group/key is the same as group_key) and also GetPath() result +// may be not what you would expect it to be. +// +// Another limitation: the keys and section names are never case-sensitive +// which might differ from wxFileConfig it it was compiled with +// wxCONFIG_CASE_SENSITIVE option. +// ---------------------------------------------------------------------------- + +// for this class, "local" file is the file appname.ini and the global file +// is the [vendor] subsection of win.ini (default for "vendor" is to be the +// same as appname). The file name (strAppName parameter) may, in fact, +// contain the full path to the file. If it doesn't, the file is searched for +// in the Windows directory. +class WXDLLEXPORT wxIniConfig : public wxConfigBase +{ +public: + // ctor & dtor + // if strAppName doesn't contain the extension and is not an absolute path, + // ".ini" is appended to it. if strVendor is empty, it's taken to be the + // same as strAppName. + wxIniConfig(const wxString& strAppName = wxEmptyString, const wxString& strVendor = wxEmptyString, + const wxString& localFilename = wxEmptyString, const wxString& globalFilename = wxEmptyString, long style = wxCONFIG_USE_LOCAL_FILE); + virtual ~wxIniConfig(); + + // implement inherited pure virtual functions + virtual void SetPath(const wxString& strPath); + virtual const wxString& GetPath() const; + + virtual bool GetFirstGroup(wxString& str, long& lIndex) const; + virtual bool GetNextGroup (wxString& str, long& lIndex) const; + virtual bool GetFirstEntry(wxString& str, long& lIndex) const; + virtual bool GetNextEntry (wxString& str, long& lIndex) const; + + virtual size_t GetNumberOfEntries(bool bRecursive = FALSE) const; + virtual size_t GetNumberOfGroups(bool bRecursive = FALSE) const; + + virtual bool HasGroup(const wxString& strName) const; + virtual bool HasEntry(const wxString& strName) const; + + // return TRUE if the current group is empty + bool IsEmpty() const; + + // read/write + bool Read(const wxString& key, wxString *pStr) const; + bool Read(const wxString& key, wxString *pStr, const wxString& szDefault) const; + bool Read(const wxString& key, long *plResult) const; + + // The following are necessary to satisfy the compiler + wxString Read(const wxString& key, const wxString& defVal) const + { return wxConfigBase::Read(key, defVal); } + bool Read(const wxString& key, long *pl, long defVal) const + { return wxConfigBase::Read(key, pl, defVal); } + long Read(const wxString& key, long defVal) const + { return wxConfigBase::Read(key, defVal); } + bool Read(const wxString& key, int *pi, int defVal) const + { return wxConfigBase::Read(key, pi, defVal); } + bool Read(const wxString& key, int *pi) const + { return wxConfigBase::Read(key, pi); } + bool Read(const wxString& key, double* val) const + { return wxConfigBase::Read(key, val); } + bool Read(const wxString& key, double* val, double defVal) const + { return wxConfigBase::Read(key, val, defVal); } + + bool Write(const wxString& key, const wxString& szValue); + bool Write(const wxString& key, long lValue); + + virtual bool Flush(bool bCurrentOnly = FALSE); + + virtual bool RenameEntry(const wxString& oldName, const wxString& newName); + virtual bool RenameGroup(const wxString& oldName, const wxString& newName); + + virtual bool DeleteEntry(const wxString& Key, bool bGroupIfEmptyAlso); + virtual bool DeleteGroup(const wxString& szKey); + virtual bool DeleteAll(); + +private: + // helpers + wxString GetPrivateKeyName(const wxString& szKey) const; + wxString GetKeyName(const wxString& szKey) const; + + wxString m_strLocalFilename; // name of the private INI file + wxString m_strGroup, // current group in appname.ini file + m_strPath; // the rest of the path (no trailing '_'!) + // Virtual function hiding + virtual bool Read(const wxString& key, bool* val) const + { return(wxConfigBase::Read(key, val));}; + virtual bool Read(const wxString& key, bool* val, bool defVal) const + { return(wxConfigBase::Read(key, val, defVal));}; + virtual bool Write(const wxString& key, double value) + { return(wxConfigBase::Write(key, value));}; + virtual bool Write(const wxString& key, bool value) + { return(wxConfigBase::Write(key, value));}; +}; + +#endif //_INICONF_H diff --git a/include/wx/os2/joystick.h b/include/wx/os2/joystick.h index 30324fc035..6e5a4c9236 100644 --- a/include/wx/os2/joystick.h +++ b/include/wx/os2/joystick.h @@ -1,21 +1,17 @@ ///////////////////////////////////////////////////////////////////////////// // Name: joystick.h // Purpose: wxJoystick class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_JOYSTICK_H_ #define _WX_JOYSTICK_H_ -#ifdef __GNUG__ -#pragma interface "joystick.h" -#endif - #include "wx/event.h" class WXDLLEXPORT wxJoystick: public wxObject diff --git a/include/wx/os2/listbox.h b/include/wx/os2/listbox.h index 967a877cfe..67d25700cc 100644 --- a/include/wx/os2/listbox.h +++ b/include/wx/os2/listbox.h @@ -1,25 +1,30 @@ ///////////////////////////////////////////////////////////////////////////// // Name: listbox.h // Purpose: wxListBox class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_LISTBOX_H_ #define _WX_LISTBOX_H_ -#ifdef __GNUG__ -#pragma interface "listbox.h" -#endif - #include "wx/control.h" WXDLLEXPORT_DATA(extern const char*) wxListBoxNameStr; +#if wxUSE_OWNER_DRAWN + class WXDLLEXPORT wxOwnerDrawn; + + // define the array of list box items + #include + + WX_DEFINE_ARRAY(wxOwnerDrawn *, wxListBoxItemsArray); +#endif + // forward decl for GetSelections() class WXDLLEXPORT wxArrayInt; @@ -53,6 +58,22 @@ class WXDLLEXPORT wxListBox: public wxControl ~wxListBox(); + bool OS2Command(WXUINT param, WXWORD id); + +#if wxUSE_OWNER_DRAWN + bool OS2OnMeasure(WXMEASUREITEMSTRUCT *item); + bool OS2OnDraw(WXDRAWITEMSTRUCT *item); + + // plug-in for derived classes + virtual wxOwnerDrawn *CreateItem(size_t n); + + // allows to get the item and use SetXXX functions to set it's appearance + wxOwnerDrawn *GetItem(size_t n) const { return m_aItems[n]; } + + // get the index of the given item + int GetItemIndex(wxOwnerDrawn *item) const { return m_aItems.Index(item); } +#endif // wxUSE_OWNER_DRAWN + virtual void Append(const wxString& item); virtual void Append(const wxString& item, void *clientData); virtual void Set(int n, const wxString* choices, char **clientData = NULL); @@ -65,15 +86,14 @@ class WXDLLEXPORT wxListBox: public wxControl // For single choice list item only virtual int GetSelection() const ; virtual void Delete(int n); - virtual char *GetClientData(int n) const ; - virtual void SetClientData(int n, char *clientData); + virtual void *GetClientData(int n) const ; + virtual void SetClientData(int n, void *clientData); virtual void SetString(int n, const wxString& s); // For single or multiple choice list item virtual int GetSelections(wxArrayInt& aSelections) const; virtual bool Selected(int n) const ; virtual wxString GetString(int n) const ; - virtual void SetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); // Set the specified item at the first visible item // or scroll to max range. @@ -88,9 +108,34 @@ class WXDLLEXPORT wxListBox: public wxControl void Command(wxCommandEvent& event); - protected: + // OS/2-PM-specific code to set the horizontal extent of + // the listbox, if necessary. If s is non-NULL, it's + // used to calculate the horizontal extent. + // Otherwise, all strings are used. + virtual void SetHorizontalExtent(const wxString& s = wxEmptyString); + + virtual WXHBRUSH OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, + WXUINT message, WXWPARAM wParam, WXLPARAM lParam); + + virtual MRESULT OS2WindowProc(HWND hwnd, WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); + virtual void SetupColours(); + +protected: int m_noItems; int m_selected; + + virtual wxSize DoGetBestSize(); + +#if wxUSE_OWNER_DRAWN + // control items + wxListBoxItemsArray m_aItems; +#endif +private: + //Virtual function hiding suppression, do not use + wxControl *CreateItem(const wxItemResource* childResource, + const wxItemResource* parentResource, + const wxResourceTable *table = (const wxResourceTable *) NULL) + { return(wxWindowBase::CreateItem(childResource, parentResource, table));}; }; #endif diff --git a/src/os2/brush.cpp b/src/os2/brush.cpp index 4f28e92f53..bf2712be01 100644 --- a/src/os2/brush.cpp +++ b/src/os2/brush.cpp @@ -81,20 +81,6 @@ wxBrush::wxBrush(const wxBitmap& stipple) wxTheBrushList->AddBrush(this); } -void wxBrush::Unshare() -{ - // Don't change shared data - if (!m_refData) - { - m_refData = new wxBrushRefData(); - } - else - { - wxBrushRefData* ref = new wxBrushRefData(*(wxBrushRefData*)m_refData); - UnRef(); - m_refData = ref; - } -} void wxBrush::SetColour(const wxColour& col) { @@ -138,3 +124,39 @@ bool wxBrush::RealizeResource() return FALSE; } +WXHANDLE wxBrush::GetResourceHandle(void) +{ + return (WXHANDLE) M_BRUSHDATA->m_hBrush; +} + +bool wxBrush::FreeResource(bool WXUNUSED(force)) +{ + if (M_BRUSHDATA && (M_BRUSHDATA->m_hBrush != 0)) + { +// TODO DeleteObject((HBRUSH) M_BRUSHDATA->m_hBrush); + M_BRUSHDATA->m_hBrush = 0; + return TRUE; + } + else return FALSE; +} + +bool wxBrush::IsFree() const +{ + return (M_BRUSHDATA && (M_BRUSHDATA->m_hBrush == 0)); +} + +void wxBrush::Unshare() +{ + // Don't change shared data + if (!m_refData) + { + m_refData = new wxBrushRefData(); + } + else + { + wxBrushRefData* ref = new wxBrushRefData(*(wxBrushRefData*)m_refData); + UnRef(); + m_refData = ref; + } +} + diff --git a/src/os2/gsocket.c b/src/os2/gsocket.c new file mode 100644 index 0000000000..4f53fa5fc0 --- /dev/null +++ b/src/os2/gsocket.c @@ -0,0 +1,1208 @@ +/* ------------------------------------------------------------------------- + * Project: GSocket (Generic Socket) for WX + * Name: gsocket.c + * Purpose: GSocket main Unix-style file + * CVSID: $Id$ + * ------------------------------------------------------------------------- + */ + +#include "wx/setup.h" +#include "wx/defs.h" + +#if wxUSE_SOCKETS + +#define BSD_SELECT // use Berkley Sockets select + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "wx/gsocket.h" +#include "wx/os2/gsockos2.h" + +#ifndef SOCKLEN_T + +#ifdef __GLIBC__ +# if __GLIBC__ == 2 +# define SOCKLEN_T socklen_t +# endif +#else +# define SOCKLEN_T int +#endif + +#endif + +/* Global initialisers */ + +bool GSocket_Init() +{ + return TRUE; +} + +void GSocket_Cleanup() +{ +} + +/* Constructors / Destructors */ + +GSocket *GSocket_new() +{ + int i; + GSocket *socket; + + socket = (GSocket *)malloc(sizeof(GSocket)); + + if (socket == NULL) + return NULL; + + socket->m_fd = -1; + for (i=0;im_cbacks[i] = NULL; + } + socket->m_detected = 0; + socket->m_local = NULL; + socket->m_peer = NULL; + socket->m_error = GSOCK_NOERROR; + socket->m_server = FALSE; + socket->m_stream = TRUE; + socket->m_gui_dependent = NULL; + socket->m_non_blocking = FALSE; + socket->m_timeout = 10*60*1000; + /* 10 minutes * 60 sec * 1000 millisec */ + socket->m_establishing = FALSE; + + /* We initialize the GUI specific entries here */ + _GSocket_GUI_Init(socket); + + return socket; +} + +void GSocket_destroy(GSocket *socket) +{ + assert(socket != NULL); + + /* First, we check that the socket is really shutdowned */ + if (socket->m_fd != -1) + GSocket_Shutdown(socket); + + /* We destroy GUI specific variables */ + _GSocket_GUI_Destroy(socket); + + /* We destroy private addresses */ + if (socket->m_local) + GAddress_destroy(socket->m_local); + + if (socket->m_peer) + GAddress_destroy(socket->m_peer); + + /* We destroy socket itself */ + free(socket); +} + +void GSocket_Shutdown(GSocket *socket) +{ + int evt; + + assert(socket != NULL); + + /* If socket has been created, we shutdown it */ + if (socket->m_fd != -1) + { + shutdown(socket->m_fd, 2); + soclose(socket->m_fd); + socket->m_fd = -1; + } + + /* We also disable GUI callbacks */ + for (evt = 0; evt < GSOCK_MAX_EVENT; evt++) + socket->m_cbacks[evt] = NULL; + + socket->m_detected = 0; + _GSocket_Disable_Events(socket); +} + +/* Address handling */ + +GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address) +{ + assert(socket != NULL); + + if ((socket->m_fd != -1 && !socket->m_server)) { + socket->m_error = GSOCK_INVSOCK; + return GSOCK_INVSOCK; + } + + if (address == NULL || address->m_family == GSOCK_NOFAMILY) { + socket->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + if (socket->m_local) + GAddress_destroy(socket->m_local); + + socket->m_local = GAddress_copy(address); + + return GSOCK_NOERROR; +} + +GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address) +{ + assert(socket != NULL); + + if (address == NULL || address->m_family == GSOCK_NOFAMILY) { + socket->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + if (socket->m_peer) + GAddress_destroy(socket->m_peer); + + socket->m_peer = GAddress_copy(address); + + return GSOCK_NOERROR; +} + +GAddress *GSocket_GetLocal(GSocket *socket) +{ + GAddress *address; + struct sockaddr addr; + SOCKLEN_T size; + GSocketError err; + + assert(socket != NULL); + + if (socket->m_local) + return GAddress_copy(socket->m_local); + + if (socket->m_fd == -1) { + socket->m_error = GSOCK_INVSOCK; + return NULL; + } + + size = sizeof(addr); + + if (getsockname(socket->m_fd, &addr, &size) < 0) { + socket->m_error = GSOCK_IOERR; + return NULL; + } + + address = GAddress_new(); + if (address == NULL) { + socket->m_error = GSOCK_MEMERR; + return NULL; + } + socket->m_error = _GAddress_translate_from(address, &addr, size); + if (socket->m_error != GSOCK_NOERROR) { + GAddress_destroy(address); + return NULL; + } + + return address; +} + +GAddress *GSocket_GetPeer(GSocket *socket) +{ + assert(socket != NULL); + + if (socket->m_peer) + return GAddress_copy(socket->m_peer); + + return NULL; +} + +/* Server specific parts */ + +/* GSocket_SetServer: + * Sets up the socket as a server. It uses the "Local" field of GSocket. + * "Local" must be set by GSocket_SetLocal() before GSocket_SetServer() + * is called. Possible error codes are: GSOCK_INVSOCK if socket has not + * been initialized, GSOCK_INVADDR if the local address has not been + * defined and GSOCK_IOERR for other internal errors. + */ +GSocketError GSocket_SetServer(GSocket *sck) +{ + int type; + int arg = 1; + + assert(sck != NULL); + + if (sck->m_fd != -1) { + sck->m_error = GSOCK_INVSOCK; + return GSOCK_INVSOCK; + } + + if (!sck->m_local) { + sck->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + /* We always have a stream here */ + sck->m_stream = TRUE; + sck->m_server = TRUE; + + /* Create the socket */ + sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0); + + if (sck->m_fd == -1) { + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + ioctl(sck->m_fd, FIONBIO, (char*)&arg, sizeof(int)); + _GSocket_Enable_Events(sck); + + /* Bind the socket to the LOCAL address */ + if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) { + soclose(sck->m_fd); + sck->m_fd = -1; + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + /* Enable listening up to 5 connections */ + if (listen(sck->m_fd, 5) < 0) { + soclose(sck->m_fd); + sck->m_fd = -1; + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + return GSOCK_NOERROR; +} + +/* GSocket_WaitConnection: + * Waits for an incoming client connection. + */ +GSocket *GSocket_WaitConnection(GSocket *socket) +{ + GSocket *connection; + int arg = 1; + + assert(socket != NULL); + + /* Reenable CONNECTION events */ + _GSocket_Enable(socket, GSOCK_CONNECTION); + + /* If the socket has already been created, we exit immediately */ + if (socket->m_fd == -1 || !socket->m_server) + { + socket->m_error = GSOCK_INVSOCK; + return NULL; + } + + /* Create a GSocket object for the new connection */ + connection = GSocket_new(); + if (!connection) + { + connection->m_error = GSOCK_MEMERR; + return NULL; + } + + /* Accept the incoming connection */ + if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT) + { + GSocket_destroy(connection); + /* socket->m_error set by _GSocket_Input_Timeout */ + return NULL; + } + + connection->m_fd = accept(socket->m_fd, NULL, NULL); + + if (connection->m_fd == -1) + { + if (errno == EWOULDBLOCK) + socket->m_error = GSOCK_WOULDBLOCK; + else + socket->m_error = GSOCK_IOERR; + + GSocket_destroy(connection); + return NULL; + } + + /* Initialize all fields */ + connection->m_server = FALSE; + connection->m_stream = TRUE; + connection->m_oriented = TRUE; + + ioctl(connection->m_fd, FIONBIO, (char*)&arg, sizeof(int)); + _GSocket_Enable_Events(connection); + + return connection; +} + +/* Non oriented connections */ + +GSocketError GSocket_SetNonOriented(GSocket *sck) +{ + int arg = 1; + + assert(sck != NULL); + + if (sck->m_fd != -1) { + sck->m_error = GSOCK_INVSOCK; + return GSOCK_INVSOCK; + } + + if (!sck->m_local) { + sck->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + sck->m_stream = FALSE; + sck->m_server = FALSE; + sck->m_oriented = FALSE; + + /* Create the socket */ + sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0); + + if (sck->m_fd < 0) { + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + ioctl(sck->m_fd, FIONBIO, (char*)&arg, sizeof(int)); + _GSocket_Enable_Events(sck); + + /* Bind it to the LOCAL address */ + if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) { + soclose(sck->m_fd); + sck->m_fd = -1; + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + return GSOCK_NOERROR; +} + +/* Client specific parts */ + +/* GSocket_Connect: + * Establishes a client connection to a server using the "Peer" + * field of GSocket. "Peer" must be set by GSocket_SetPeer() before + * GSocket_Connect() is called. Possible error codes are GSOCK_INVSOCK, + * GSOCK_INVADDR, GSOCK_TIMEDOUT, GSOCK_WOULDBLOCK and GSOCK_IOERR. + * If a socket is nonblocking and Connect() returns GSOCK_WOULDBLOCK, + * the connection request can be completed later. Use GSocket_Select() + * to check or wait for a GSOCK_CONNECTION event. + */ +GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) +{ + int type, err, ret; + int arg = 1; + + assert(sck != NULL); + + /* Enable CONNECTION events (needed for nonblocking connections) */ + _GSocket_Enable(sck, GSOCK_CONNECTION); + + if (sck->m_fd != -1) + { + sck->m_error = GSOCK_INVSOCK; + return GSOCK_INVSOCK; + } + + if (!sck->m_peer) + { + sck->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + /* Test whether we want the socket to be a stream (e.g. TCP) */ + sck->m_stream = (stream == GSOCK_STREAMED); + sck->m_oriented = TRUE; + sck->m_server = FALSE; + sck->m_establishing = FALSE; + + if (sck->m_stream) + type = SOCK_STREAM; + else + type = SOCK_DGRAM; + + /* Create the socket */ + sck->m_fd = socket(sck->m_peer->m_realfamily, type, 0); + + if (sck->m_fd == -1) { + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + ioctl(sck->m_fd, FIONBIO, (char*)&arg, sizeof(int)); + _GSocket_Enable_Events(sck); + + /* Connect it to the PEER address */ + ret = connect(sck->m_fd, sck->m_peer->m_addr, sck->m_peer->m_len); + + if (ret == -1) + { + err = errno; + + /* If connect failed with EINPROGRESS and the GSocket object + * is in blocking mode, we select() for the specified timeout + * checking for writability to see if the connection request + * completes. + */ + if ((err == EINPROGRESS) && (!sck->m_non_blocking)) + { + if (_GSocket_Output_Timeout(sck) == GSOCK_TIMEDOUT) + { + soclose(sck->m_fd); + sck->m_fd = -1; + /* sck->m_error is set in _GSocket_Output_Timeout */ + fprintf(stderr, "Blocking connect timeouts\n"); + return GSOCK_TIMEDOUT; + } + else + { + fprintf(stderr, "Blocking connect OK\n"); + return GSOCK_NOERROR; + } + } + + /* If connect failed with EINPROGRESS and the GSocket object + * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK + * (and return GSOCK_WOULDBLOCK) but we don't close the socket; + * this way if the connection completes, a GSOCK_CONNECTION + * event will be generated, if enabled. + */ + if ((err == EINPROGRESS) && (sck->m_non_blocking)) + { + sck->m_error = GSOCK_WOULDBLOCK; + sck->m_establishing = TRUE; + fprintf(stderr, "Nonblocking connect in progress\n"); + + return GSOCK_WOULDBLOCK; + } + + /* If connect failed with an error other than EINPROGRESS, + * then the call to GSocket_Connect has failed. + */ + soclose(sck->m_fd); + sck->m_fd = -1; + sck->m_error = GSOCK_IOERR; + + fprintf(stderr, "Connect failed (generic err)\n"); + return GSOCK_IOERR; + } + + fprintf(stderr, "Connect OK\n"); + return GSOCK_NOERROR; +} + +/* Generic IO */ + +/* Like recv(), send(), ... */ +int GSocket_Read(GSocket *socket, char *buffer, int size) +{ + int ret; + + assert(socket != NULL); + + /* Reenable INPUT events */ + _GSocket_Enable(socket, GSOCK_INPUT); + + if (socket->m_fd == -1 || socket->m_server) + { + socket->m_error = GSOCK_INVSOCK; + return -1; + } + + if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT) + return -1; + + if (socket->m_stream) + ret = _GSocket_Recv_Stream(socket, buffer, size); + else + ret = _GSocket_Recv_Dgram(socket, buffer, size); + + if (ret == -1) + { + if (errno == EWOULDBLOCK) + socket->m_error = GSOCK_WOULDBLOCK; + else + socket->m_error = GSOCK_IOERR; + } + + return ret; +} + +int GSocket_Write(GSocket *socket, const char *buffer, + int size) +{ + int ret; + + assert(socket != NULL); + + if (socket->m_fd == -1 || socket->m_server) + { + socket->m_error = GSOCK_INVSOCK; + return -1; + } + + if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT) + return -1; + + if (socket->m_stream) + ret = _GSocket_Send_Stream(socket, buffer, size); + else + ret = _GSocket_Send_Dgram(socket, buffer, size); + + if (ret == -1) + { + if (errno == EWOULDBLOCK) + socket->m_error = GSOCK_WOULDBLOCK; + else + socket->m_error = GSOCK_IOERR; + + /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect + * in MSW). Once the first OUTPUT event is received, users can assume + * that the socket is writable until a read operation fails. Only then + * will further OUTPUT events be posted. + */ + _GSocket_Enable(socket, GSOCK_OUTPUT); + } + + return ret; +} + +/* GSocket_Select: + * Polls the socket to determine its status. This function will + * check for the events specified in the 'flags' parameter, and + * it will return a mask indicating which operations can be + * performed. This function won't block, regardless of the + * mode (blocking|nonblocking) of the socket. + */ +GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags) +{ + assert(socket != NULL); + + return (flags & socket->m_detected); +} + +/* Flags */ + +/* GSocket_SetNonBlocking: + * Sets the socket to non-blocking mode. This is useful if + * we don't want to wait. + */ +void GSocket_SetNonBlocking(GSocket *socket, bool non_block) +{ + assert(socket != NULL); + + socket->m_non_blocking = non_block; +} + +/* GSocket_SetTimeout: + * Sets the timeout for blocking calls. Time is + * expressed in milliseconds. + */ +void GSocket_SetTimeout(GSocket *socket, unsigned long millisec) +{ + assert(socket != NULL); + + socket->m_timeout = millisec; +} + +/* GSocket_GetError: + * Returns the last error occured for this socket. + */ +GSocketError GSocket_GetError(GSocket *socket) +{ + assert(socket != NULL); + + return socket->m_error; +} + +/* Callbacks */ + +/* Only one callback is possible for each event (INPUT, OUTPUT, CONNECTION + * and LOST). The callbacks are called in the following situations: + * + * INPUT: There is at least one byte in the input buffer + * OUTPUT: The system is sure that the next write call will not block + * CONNECTION: Two cases are possible: + * Client socket -> the connection is established + * Server socket -> a client requests a connection + * LOST: The connection is lost + * + * An event is generated only once and its state is reseted when the + * relative IO call is requested. + * For example: INPUT -> GSocket_Read() + * CONNECTION -> GSocket_Accept() + */ + +/* GSocket_SetCallback: + * Enables the callbacks specified by 'flags'. Note that 'flags' + * may be a combination of flags OR'ed toghether, so the same + * callback function can be made to accept different events. + * The callback function must have the following prototype: + * + * void function(GSocket *socket, GSocketEvent event, char *cdata) + */ +void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags, + GSocketCallback callback, char *cdata) +{ + int count; + + assert(socket != NULL); + + for (count = 0; count < GSOCK_MAX_EVENT; count++) + { + if ((flags & (1 << count)) != 0) + { + socket->m_cbacks[count] = callback; + socket->m_data[count] = cdata; + } + } +} + +/* GSocket_UnsetCallback: + * Disables all callbacks specified by 'flags', which may be a + * combination of flags OR'ed toghether. + */ +void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags) +{ + int count; + + assert(socket != NULL); + + for (count = 0; count < GSOCK_MAX_EVENT; count++) + { + if ((flags & (1 << count)) != 0) + { + socket->m_cbacks[count] = NULL; + socket->m_data[count] = NULL; + } + } +} + +#define CALL_CALLBACK(socket, event) { \ + _GSocket_Disable(socket, event); \ + if (socket->m_cbacks[event]) \ + socket->m_cbacks[event](socket, event, socket->m_data[event]); \ +} + + +void _GSocket_Enable(GSocket *socket, GSocketEvent event) +{ + socket->m_detected &= ~(1 << event); + _GSocket_Install_Callback(socket, event); +} + +void _GSocket_Disable(GSocket *socket, GSocketEvent event) +{ + socket->m_detected |= (1 << event); + _GSocket_Uninstall_Callback(socket, event); +} + +/* _GSocket_Input_Timeout: + * For blocking sockets, wait until data is available or + * until timeout ellapses. + */ +GSocketError _GSocket_Input_Timeout(GSocket *socket) +{ + struct timeval tv; + fd_set readfds; + + tv.tv_sec = (socket->m_timeout / 1000); + tv.tv_usec = (socket->m_timeout % 1000) * 1000; + + if (!socket->m_non_blocking) + { + FD_ZERO(&readfds); + FD_SET(socket->m_fd, &readfds); + if (select(socket->m_fd + 1, &readfds, NULL, NULL, &tv) == 0) + { + socket->m_error = GSOCK_TIMEDOUT; + return GSOCK_TIMEDOUT; + } + } + return GSOCK_NOERROR; +} + +/* _GSocket_Output_Timeout: + * For blocking sockets, wait until data can be sent without + * blocking or until timeout ellapses. + */ +GSocketError _GSocket_Output_Timeout(GSocket *socket) +{ + struct timeval tv; + fd_set writefds; + + tv.tv_sec = (socket->m_timeout / 1000); + tv.tv_usec = (socket->m_timeout % 1000) * 1000; + + if (!socket->m_non_blocking) + { + FD_ZERO(&writefds); + FD_SET(socket->m_fd, &writefds); + if (select(socket->m_fd + 1, NULL, &writefds, NULL, &tv) == 0) + { + socket->m_error = GSOCK_TIMEDOUT; + return GSOCK_TIMEDOUT; + } + } + return GSOCK_NOERROR; +} + +int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size) +{ + int ret; + + ret = recv(socket->m_fd, buffer, size, 0); + + return ret; +} + +int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size) +{ + struct sockaddr from; + SOCKLEN_T fromlen; + int ret; + GSocketError err; + + fromlen = sizeof(from); + + ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen); + + if (ret == -1) + return -1; + + /* Translate a system address into a GSocket address */ + if (!socket->m_peer) + { + socket->m_peer = GAddress_new(); + if (!socket->m_peer) + { + socket->m_error = GSOCK_MEMERR; + return -1; + } + } + err = _GAddress_translate_from(socket->m_peer, &from, fromlen); + if (err != GSOCK_NOERROR) + { + GAddress_destroy(socket->m_peer); + socket->m_peer = NULL; + socket->m_error = err; + return -1; + } + + return ret; +} + +int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size) +{ + int ret; + GSocketError err; + + ret = send(socket->m_fd, (char*)buffer, size, 0); + + return ret; +} + +int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size) +{ + struct sockaddr *addr; + int len, ret; + GSocketError err; + + if (!socket->m_peer) { + socket->m_error = GSOCK_INVADDR; + return -1; + } + + err = _GAddress_translate_to(socket->m_peer, &addr, &len); + if (err != GSOCK_NOERROR) { + socket->m_error = err; + return -1; + } + + ret = sendto(socket->m_fd, (char*)buffer, size, 0, addr, len); + + /* Frees memory allocated from _GAddress_translate_to */ + free(addr); + + return ret; +} + +void _GSocket_Detected_Read(GSocket *socket) +{ + char c; + int ret; + + if (socket->m_stream) + { + ret = recv(socket->m_fd, &c, 1, MSG_PEEK); + + if (ret < 0 && socket->m_server) + { + CALL_CALLBACK(socket, GSOCK_CONNECTION); + return; + } + + if (ret > 0) + { + CALL_CALLBACK(socket, GSOCK_INPUT); + } + else + { + CALL_CALLBACK(socket, GSOCK_LOST); + } + } +} + +void _GSocket_Detected_Write(GSocket *socket) +{ + if (socket->m_establishing && !socket->m_server) + { + int error, len; + + socket->m_establishing = FALSE; + + len = sizeof(error); + getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len); + + if (error) + { + CALL_CALLBACK(socket, GSOCK_LOST); + } + else + { + CALL_CALLBACK(socket, GSOCK_CONNECTION); + /* We have to fire this event by hand because CONNECTION (for clients) + * and OUTPUT are internally the same and we just disabled CONNECTION + * events with the above macro. + */ + CALL_CALLBACK(socket, GSOCK_OUTPUT); + } + } + else + { + CALL_CALLBACK(socket, GSOCK_OUTPUT); + } +} + +/* + * ------------------------------------------------------------------------- + * GAddress + * ------------------------------------------------------------------------- + */ + +/* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY or + * GSOCK_*family*. In case it is GSOCK_NOFAMILY, it initializes address to be + * a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR. + */ +#define CHECK_ADDRESS(address, family, retval) \ +{ \ + if (address->m_family == GSOCK_NOFAMILY) \ + if (_GAddress_Init_##family(address) != GSOCK_NOERROR) {\ + return address->m_error; \ + }\ + if (address->m_family != GSOCK_##family) {\ + address->m_error = GSOCK_INVADDR; \ + return retval; \ + } \ +} + +GAddress *GAddress_new() +{ + GAddress *address; + + address = (GAddress *)malloc(sizeof(GAddress)); + + if (address == NULL) + return NULL; + + address->m_family = GSOCK_NOFAMILY; + address->m_addr = NULL; + address->m_len = 0; + + return address; +} + +GAddress *GAddress_copy(GAddress *address) +{ + GAddress *addr2; + + assert(address != NULL); + + addr2 = (GAddress *)malloc(sizeof(GAddress)); + + if (addr2 == NULL) + return NULL; + + memcpy(addr2, address, sizeof(GAddress)); + + if (address->m_addr) { + addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len); + if (addr2->m_addr == NULL) { + free(addr2); + return NULL; + } + memcpy(addr2->m_addr, address->m_addr, addr2->m_len); + } + + return addr2; +} + +void GAddress_destroy(GAddress *address) +{ + assert(address != NULL); + + free(address); +} + +void GAddress_SetFamily(GAddress *address, GAddressType type) +{ + assert(address != NULL); + + address->m_family = type; +} + +GAddressType GAddress_GetFamily(GAddress *address) +{ + assert(address != NULL); + + return address->m_family; +} + +GSocketError _GAddress_translate_from(GAddress *address, struct sockaddr *addr, int len){ + address->m_realfamily = addr->sa_family; + switch (addr->sa_family) { + case AF_INET: + address->m_family = GSOCK_INET; + break; + case AF_UNIX: + address->m_family = GSOCK_UNIX; + break; +#ifdef AF_INET6 + case AF_INET6: + address->m_family = GSOCK_INET6; + break; +#endif + default: + { + address->m_error = GSOCK_INVOP; + return GSOCK_INVOP; + } + } + + if (address->m_addr) + free(address->m_addr); + + address->m_len = len; + address->m_addr = (struct sockaddr *)malloc(len); + if (address->m_addr == NULL) { + address->m_error = GSOCK_MEMERR; + return GSOCK_MEMERR; + } + memcpy(address->m_addr, addr, len); + + return GSOCK_NOERROR; +} + +GSocketError _GAddress_translate_to(GAddress *address, + struct sockaddr **addr, int *len) +{ + if (!address->m_addr) { + address->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + *len = address->m_len; + *addr = (struct sockaddr *)malloc(address->m_len); + if (*addr == NULL) { + address->m_error = GSOCK_MEMERR; + return GSOCK_MEMERR; + } + + memcpy(*addr, address->m_addr, address->m_len); + return GSOCK_NOERROR; +} + +/* + * ------------------------------------------------------------------------- + * Internet address family + * ------------------------------------------------------------------------- + */ + +GSocketError _GAddress_Init_INET(GAddress *address) +{ + address->m_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in)); + if (address->m_addr == NULL) { + address->m_error = GSOCK_MEMERR; + return GSOCK_MEMERR; + } + + address->m_len = sizeof(struct sockaddr_in); + + address->m_family = GSOCK_INET; + address->m_realfamily = PF_INET; + ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET; + ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY; + + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname) +{ + struct hostent *he; + struct in_addr *addr; + + assert(address != NULL); + + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr); + + /* If it is a numeric host name, convert it now */ +#if defined(HAVE_INET_ATON) + if (inet_aton(hostname, addr) == 0) { +#elif defined(HAVE_INET_ADDR) + /* Fix from Guillermo Rodriguez Garcia */ + if ( (addr->s_addr = inet_addr(hostname)) == -1 ) { +#endif + struct in_addr *array_addr; + + /* It is a real name, we solve it */ + he = gethostbyname((char*)hostname); + if (he == NULL) { + address->m_error = GSOCK_NOHOST; + return GSOCK_NOHOST; + } + array_addr = (struct in_addr *) *(he->h_addr_list); + addr->s_addr = array_addr[0].s_addr; +#if defined(HAVE_INET_ATON) + } +#elif defined(HAVE_INET_ADDR) + } +#endif + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_SetHostAddress(GAddress *address, + unsigned long hostaddr) +{ + struct in_addr *addr; + + assert(address != NULL); + + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr); + addr->s_addr = hostaddr; + + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port, + const char *protocol) +{ + struct servent *se; + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + if (!port) { + address->m_error = GSOCK_INVPORT; + return GSOCK_INVPORT; + } + + se = getservbyname((char*)port, (char*)protocol); + if (!se) { + if (isdigit(port[0])) { + int port_int; + + port_int = atoi(port); + addr = (struct sockaddr_in *)address->m_addr; + addr->sin_port = htons(port_int); + return GSOCK_NOERROR; + } + + address->m_error = GSOCK_INVPORT; + return GSOCK_INVPORT; + } + + addr = (struct sockaddr_in *)address->m_addr; + addr->sin_port = se->s_port; + + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port) +{ + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + addr = (struct sockaddr_in *)address->m_addr; + addr->sin_port = htons(port); + + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf) +{ + struct hostent *he; + char *addr_buf; + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + addr = (struct sockaddr_in *)address->m_addr; + addr_buf = (char *)&(addr->sin_addr); + + he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET); + if (he == NULL) { + address->m_error = GSOCK_NOHOST; + return GSOCK_NOHOST; + } + + strncpy(hostname, he->h_name, sbuf); + + return GSOCK_NOERROR; +} + +unsigned long GAddress_INET_GetHostAddress(GAddress *address) +{ + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, 0); + + addr = (struct sockaddr_in *)address->m_addr; + + return addr->sin_addr.s_addr; +} + +unsigned short GAddress_INET_GetPort(GAddress *address) +{ + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, 0); + + addr = (struct sockaddr_in *)address->m_addr; + return ntohs(addr->sin_port); +} + +#endif + /* wxUSE_SOCKETS */ diff --git a/src/os2/helpwin.cpp b/src/os2/helpwin.cpp new file mode 100644 index 0000000000..3d7e6c1360 --- /dev/null +++ b/src/os2/helpwin.cpp @@ -0,0 +1,148 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: helpwin.cpp +// Purpose: Help system: native implementation +// Author: David Webster +// Modified by: +// Created: 10/09/99 +// RCS-ID: $Id$ +// Copyright: (c) David Webster +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef WX_PRECOMP +#include "wx/defs.h" +#endif + +#include "wx/os2/helpwin.h" + +#if wxUSE_HELP +#include + +#include + +#include + +// MAX path length +#define _MAXPATHLEN 500 + +// MAX length of Help descriptor +#define _MAX_HELP_LEN 500 + +#if !USE_SHARED_LIBRARY +IMPLEMENT_DYNAMIC_CLASS(wxWinHelpController, wxHelpControllerBase) +#endif + +wxWinHelpController::wxWinHelpController() +{ + m_helpFile = ""; +} + +wxWinHelpController::~wxWinHelpController() +{ +} + +bool wxWinHelpController::Initialize(const wxString& filename) +{ + m_helpFile = filename; + // TODO any other inits + return TRUE; +} + +bool wxWinHelpController::LoadFile(const wxString& file) +{ + m_helpFile = file; + // TODO + return TRUE; +} + +bool wxWinHelpController::DisplayContents() +{ + if (m_helpFile == wxT("")) return FALSE; + + wxString str = m_helpFile; + size_t len = str.Length(); + if (!(str[(size_t)(len-1)] == wxT('p') && str[(size_t)(len-2)] == wxT('l') && str[(size_t)(len-3)] == wxT('h') && str[(size_t)(len-4)] == wxT('.'))) + str += wxT(".hlp"); + + if (wxTheApp->GetTopWindow()) + { + // TODO : display the help + return TRUE; + } + return FALSE; +} + +bool wxWinHelpController::DisplaySection(int section) +{ + // Use context number + if (m_helpFile == wxT("")) return FALSE; + + wxString str = m_helpFile; + size_t len = str.Length(); + if (!(str[(size_t)(len-1)] == wxT('p') && str[(size_t)(len-2)] == wxT('l') && str[(size_t)(len-3)] == wxT('h') && str[(size_t)(len-4)] == wxT('.'))) + str += wxT(".hlp"); + + if (wxTheApp->GetTopWindow()) + { + // TODO :: + // WinHelp((HWND) wxTheApp->GetTopWindow()->GetHWND(), (const wxChar*) str, HELP_CONTEXT, (DWORD)section); + return TRUE; + } + return FALSE; +} + +bool wxWinHelpController::DisplayBlock(long block) +{ + // Use context number -- a very rough equivalent to block id! + if (m_helpFile == wxT("")) return FALSE; + + wxString str = m_helpFile; + size_t len = str.Length(); + if (!(str[(size_t)(len-1)] == 'p' && str[(size_t)(len-2)] == 'l' && str[(size_t)(len-3)] == 'h' && str[(size_t)(len-4)] == '.')) + str += wxT(".hlp"); + + if (wxTheApp->GetTopWindow()) + { + // TODO: + // WinHelp((HWND) wxTheApp->GetTopWindow()->GetHWND(), (const wxChar*) str, HELP_CONTEXT, (DWORD)block); + return TRUE; + } + return FALSE; +} + +bool wxWinHelpController::KeywordSearch(const wxString& k) +{ + if (m_helpFile == "") return FALSE; + + wxString str = m_helpFile; + size_t len = str.Length(); + if (!(str[(size_t)(len-1)] == wxT('p') && str[(size_t)(len-2)] == wxT('l') && str[(size_t)(len-3)] == wxT('h') && str[(size_t)(len-4)] == wxT('.'))) + str += wxT(".hlp"); + + if (wxTheApp->GetTopWindow()) + { + // TODO: + // WinHelp((HWND) wxTheApp->GetTopWindow()->GetHWND(), (const wxChar*) str, HELP_PARTIALKEY, (DWORD)(const wxChar*) k); + return TRUE; + } + return FALSE; +} + +// Can't close the help window explicitly in WinHelp +bool wxWinHelpController::Quit() +{ + if (wxTheApp->GetTopWindow()) + { + // TODO: + // WinHelp((HWND) wxTheApp->GetTopWindow()->GetHWND(), 0, HELP_QUIT, 0L); + return TRUE; + } + else + return FALSE; +} + +void wxWinHelpController::OnQuit() +{ +} +#endif // wxUSE_HELP + diff --git a/src/os2/helpxxxx.cpp b/src/os2/helpxxxx.cpp deleted file mode 100644 index 086762c646..0000000000 --- a/src/os2/helpxxxx.cpp +++ /dev/null @@ -1,83 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: helpxxxx.cpp -// Purpose: Help system: native implementation -// Author: AUTHOR -// Modified by: -// Created: ??/??/98 -// RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifdef __GNUG__ -#pragma implementation "helpxxxx.h" -#endif - -#include "wx/stubs/helpxxxx.h" - -#include - -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxXXXXHelpController, wxHelpControllerBase) -#endif - -wxXXXXHelpController::wxXXXXHelpController() -{ - m_helpFile = ""; -} - -wxXXXXHelpController::~wxXXXXHelpController() -{ -} - -bool wxXXXXHelpController::Initialize(const wxString& filename) -{ - m_helpFile = filename; - // TODO any other inits - return TRUE; -} - -bool wxXXXXHelpController::LoadFile(const wxString& file) -{ - m_helpFile = file; - // TODO - return TRUE; -} - -bool wxXXXXHelpController::DisplayContents() -{ - // TODO - return FALSE; -} - -bool wxXXXXHelpController::DisplaySection(int section) -{ - // TODO - return FALSE; -} - -bool wxXXXXHelpController::DisplayBlock(long block) -{ - // TODO - return FALSE; -} - -bool wxXXXXHelpController::KeywordSearch(const wxString& k) -{ - if (m_helpFile == "") return FALSE; - - // TODO - return FALSE; -} - -// Can't close the help window explicitly in WinHelp -bool wxXXXXHelpController::Quit() -{ - // TODO - return FALSE; -} - -void wxXXXXHelpController::OnQuit() -{ -} - diff --git a/src/os2/icon.cpp b/src/os2/icon.cpp index 6deee7dbdc..60614db09c 100644 --- a/src/os2/icon.cpp +++ b/src/os2/icon.cpp @@ -1,37 +1,55 @@ ///////////////////////////////////////////////////////////////////////////// // Name: icon.cpp // Purpose: wxIcon class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "icon.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop #endif +#ifndef WX_PRECOMP +#include +#include "wx/setup.h" +#include "wx/list.h" +#include "wx/utils.h" +#include "wx/app.h" +#include "wx/icon.h" +#endif + +#include "wx/os2/private.h" +#include "assert.h" + #include "wx/icon.h" #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxIcon, wxBitmap) +IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxBitmapHandler) +IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxBitmapHandler) #endif /* * Icons */ - wxIconRefData::wxIconRefData() { - // TODO: init icon handle + m_hIcon = (WXHICON) NULL ; } wxIconRefData::~wxIconRefData() { - // TODO: destroy icon handle + if ( m_hIcon ) + return; + // TODO ::DestroyIcon((HICON) m_hIcon); } wxIcon::wxIcon() @@ -63,8 +81,70 @@ bool wxIcon::LoadFile(const wxString& filename, long type, wxBitmapHandler *handler = FindHandler(type); if ( handler ) - return handler->LoadFile(this, filename, type, desiredWidth, desiredHeight); + return handler->LoadFile(this, filename, type, desiredWidth, desiredHeight); else - return FALSE; + return FALSE; +} + +void wxIcon::SetHICON(WXHICON ico) +{ + if ( !M_ICONDATA ) + m_refData = new wxIconRefData; + + M_ICONDATA->m_hIcon = ico; +} + +bool wxICOFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight) +{ + return FALSE; +} + +bool wxICOResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight) +{ +// TODO +/* + if ( bitmap->IsKindOf(CLASSINFO(wxIcon)) ) + { + if (desiredWidth > -1 && desiredHeight > -1) + { + M_ICONHANDLERDATA->m_hIcon = (WXHICON) ::LoadImage(wxGetInstance(), name, IMAGE_ICON, desiredWidth, desiredHeight, LR_DEFAULTCOLOR); + } + else + { + M_ICONHANDLERDATA->m_hIcon = (WXHICON) ::LoadIcon(wxGetInstance(), name); + } + + ICONINFO info ; + if (::GetIconInfo((HICON) M_ICONHANDLERDATA->m_hIcon, &info)) + { + HBITMAP ms_bitmap = info.hbmMask ; + if (ms_bitmap) + { + BITMAP bm; + ::GetObject(ms_bitmap, sizeof(BITMAP), (LPSTR) &bm); + M_ICONHANDLERDATA->m_width = bm.bmWidth; + M_ICONHANDLERDATA->m_height = bm.bmHeight; + } + if (info.hbmMask) + ::DeleteObject(info.hbmMask) ; + if (info.hbmColor) + ::DeleteObject(info.hbmColor) ; + } + } + // Override the found values with desired values + if (desiredWidth > -1 && desiredHeight > -1) + { + M_ICONHANDLERDATA->m_width = desiredWidth; + M_ICONHANDLERDATA->m_height = desiredHeight; + } + + M_ICONHANDLERDATA->m_ok = (M_ICONHANDLERDATA->m_hIcon != 0); + return M_ICONHANDLERDATA->m_ok; + } + else +*/ + return FALSE; } diff --git a/src/os2/imaglist.cpp b/src/os2/imaglist.cpp index 4cb47b4e69..a74bfc923b 100644 --- a/src/os2/imaglist.cpp +++ b/src/os2/imaglist.cpp @@ -1,19 +1,31 @@ ///////////////////////////////////////////////////////////////////////////// // Name: imaglist.cpp // Purpose: wxImageList. You may wish to use the generic version. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "imaglist.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#include +#include "wx/setup.h" +#include "wx/window.h" +#include "wx/icon.h" +#include "wx/dc.h" +#include "wx/string.h" #endif -#include "wx/stubs/imaglist.h" +#include "wx/log.h" +#include "wx/intl.h" + +#include "wx/os2/imaglist.h" +#include "wx/os2/private.h" #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxImageList, wxObject) @@ -21,23 +33,25 @@ IMPLEMENT_DYNAMIC_CLASS(wxImageList, wxObject) wxImageList::wxImageList() { - // TODO: init image list handle, if any + m_hImageList = 0; } wxImageList::~wxImageList() { - // TODO: destroy image list handle, if any + if ( m_hImageList ) + return; +// TODO: ImageList_Destroy((HIMAGELIST) m_hImageList); + m_hImageList = 0; } - // Attributes //////////////////////////////////////////////////////////////////////////// // Returns the number of images in the image list. int wxImageList::GetImageCount() const { - // TODO - return 0; + // TODO:: return ImageList_GetImageCount((HIMAGELIST) m_hImageList); + return 0; } // Operations @@ -46,8 +60,13 @@ int wxImageList::GetImageCount() const // Creates an image list bool wxImageList::Create(int width, int height, bool mask, int initial) { - // TODO - return FALSE; + UINT flags = 0; +// if ( mask ) + // TODO flags |= ILC_MASK; + + // Grow by 1, I guess this is reasonable behaviour most of the time + // m_hImageList = (WXHIMAGELIST) ImageList_Create(width, height, flags, initial, 1); + return (m_hImageList != 0); } // Adds a bitmap, and optionally a mask bitmap. @@ -55,8 +74,17 @@ bool wxImageList::Create(int width, int height, bool mask, int initial) // 'bitmap' and 'mask'. int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask) { - // TODO - return 0; + HBITMAP hBitmap1 = (HBITMAP) bitmap.GetHBITMAP(); + HBITMAP hBitmap2 = 0; + if ( mask.Ok() ) + hBitmap2 = (HBITMAP) mask.GetHBITMAP(); + + int index; // = ImageList_Add((HIMAGELIST) GetHIMAGELIST(), hBitmap1, hBitmap2); + if ( index == -1 ) + { + wxLogError(wxT("Couldn't add an image to the image list.")); + } + return index; } // Adds a bitmap, using the specified colour to create the mask bitmap @@ -64,15 +92,19 @@ int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask) // 'bitmap'. int wxImageList::Add(const wxBitmap& bitmap, const wxColour& maskColour) { - // TODO - return 0; + HBITMAP hBitmap1 = (HBITMAP) bitmap.GetHBITMAP(); + //TODO: +// COLORREF colorRef = PALETTERGB(maskColour.Red(), maskColour.Green(), maskColour.Blue()); +// return ImageList_AddMasked((HIMAGELIST) GetHIMAGELIST(), hBitmap1, colorRef); + return 0; } // Adds a bitmap and mask from an icon. int wxImageList::Add(const wxIcon& icon) { - // TODO - return 0; + HICON hIcon = (HICON) icon.GetHICON(); +// TODO: return ImageList_AddIcon((HIMAGELIST) GetHIMAGELIST(), hIcon); + return 0; } // Replaces a bitmap, optionally passing a mask bitmap. @@ -80,29 +112,38 @@ int wxImageList::Add(const wxIcon& icon) // 'bitmap' and 'mask'. bool wxImageList::Replace(int index, const wxBitmap& bitmap, const wxBitmap& mask) { - // TODO - return 0; + HBITMAP hBitmap1 = (HBITMAP) bitmap.GetHBITMAP(); + HBITMAP hBitmap2 = 0; + if ( mask.Ok() ) + hBitmap2 = (HBITMAP) mask.GetHBITMAP(); + // TODO: return (ImageList_Replace((HIMAGELIST) GetHIMAGELIST(), index, hBitmap1, hBitmap2) != 0); + return TRUE; } // Replaces a bitmap and mask from an icon. bool wxImageList::Replace(int index, const wxIcon& icon) { - // TODO - return 0; + HICON hIcon = (HICON) icon.GetHICON(); + // TODO: return (ImageList_ReplaceIcon((HIMAGELIST) GetHIMAGELIST(), index, hIcon) != 0); + return FALSE; } // Removes the image at the given index. bool wxImageList::Remove(int index) { - // TODO + // TODO return (ImageList_Remove((HIMAGELIST) GetHIMAGELIST(), index) != 0); + return FALSE; } -// Remove all images -bool wxImageList::RemoveAll() +bool wxImageList::RemoveAll(void) { - // TODO - return FALSE; + // TODO: Is this correct? + while ( GetImageCount() > 0 ) + { + Remove(0); + } + return TRUE; } // Draws the given image on a dc at the specified position. @@ -112,7 +153,40 @@ bool wxImageList::RemoveAll() bool wxImageList::Draw(int index, wxDC& dc, int x, int y, int flags, bool solidBackground) { - // TODO + HDC hDC = (HDC) dc.GetHDC(); + if ( !hDC ) return FALSE; + + if ( solidBackground ) + { + wxBrush *brush = & dc.GetBackground(); + if ( brush && brush->Ok()) + { + wxColour col(brush->GetColour()); +// ImageList_SetBkColor((HIMAGELIST) GetHIMAGELIST(), +// PALETTERGB(col.Red(), col.Green(), col.Blue())); + } +// else +// ImageList_SetBkColor((HIMAGELIST) GetHIMAGELIST(), +// CLR_NONE); + } +// else +// ImageList_SetBkColor((HIMAGELIST) GetHIMAGELIST(), +// CLR_NONE); + + UINT style = 0; +/* + if ( flags & wxIMAGELIST_DRAW_NORMAL ) + style |= ILD_NORMAL; + if ( flags & wxIMAGELIST_DRAW_TRANSPARENT ) + style |= ILD_TRANSPARENT; + if ( flags & wxIMAGELIST_DRAW_SELECTED ) + style |= ILD_SELECTED; + if ( flags & wxIMAGELIST_DRAW_FOCUSED ) + style |= ILD_FOCUS; + return (ImageList_Draw((HIMAGELIST) GetHIMAGELIST(), index, hDC, + x, y, style) != 0); +*/ + return TRUE; } diff --git a/src/os2/iniconf.cpp b/src/os2/iniconf.cpp new file mode 100644 index 0000000000..a72bbfa961 --- /dev/null +++ b/src/os2/iniconf.cpp @@ -0,0 +1,463 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/os2/iniconf.cpp +// Purpose: implementation of wxIniConfig class +// Author: David Webster +// Modified by: +// Created: 10/09/99 +// Copyright: David Webster +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include + #include + #include + #include + #include +#endif //WX_PRECOMP + +#include +#include +#include + +#include + +#define INCL_PM +#include + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// we replace all path separators with this character +#define PATH_SEP_REPLACE '_' + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// ctor & dtor +// ---------------------------------------------------------------------------- + +wxIniConfig::wxIniConfig(const wxString& strAppName, + const wxString& strVendor, + const wxString& localFilename, + const wxString& globalFilename, + long style) + : wxConfigBase(!strAppName && wxTheApp ? wxTheApp->GetAppName() + : strAppName, + !strVendor ? (wxTheApp ? wxTheApp->GetVendorName() + : strAppName) + : strVendor, + localFilename, globalFilename, style) +{ + m_strLocalFilename = localFilename; + if (m_strLocalFilename.IsEmpty()) + { + m_strLocalFilename = GetAppName() + ".ini"; + } + + // append the extension if none given and it's not an absolute file name + // (otherwise we assume that they know what they're doing) + if ( !wxIsPathSeparator(m_strLocalFilename[0u]) && + m_strLocalFilename.Find('.') == wxNOT_FOUND ) + { + m_strLocalFilename << ".ini"; + } + + // set root path + SetPath(""); +} + +wxIniConfig::~wxIniConfig() +{ +} + +// ---------------------------------------------------------------------------- +// path management +// ---------------------------------------------------------------------------- + +void wxIniConfig::SetPath(const wxString& strPath) +{ + wxArrayString aParts; + + if ( strPath.IsEmpty() ) { + // nothing + } + else if ( strPath[0u] == wxCONFIG_PATH_SEPARATOR ) { + // absolute path + wxSplitPath(aParts, strPath); + } + else { + // relative path, combine with current one + wxString strFullPath = GetPath(); + strFullPath << wxCONFIG_PATH_SEPARATOR << strPath; + wxSplitPath(aParts, strFullPath); + } + + size_t nPartsCount = aParts.Count(); + m_strPath.Empty(); + if ( nPartsCount == 0 ) { + // go to the root + m_strGroup = PATH_SEP_REPLACE; + } + else { + // translate + m_strGroup = aParts[0u]; + for ( size_t nPart = 1; nPart < nPartsCount; nPart++ ) { + if ( nPart > 1 ) + m_strPath << PATH_SEP_REPLACE; + m_strPath << aParts[nPart]; + } + } + + // other functions assume that all this is true, i.e. there are no trailing + // underscores at the end except if the group is the root one + wxASSERT( (m_strPath.IsEmpty() || m_strPath.Last() != PATH_SEP_REPLACE) && + (m_strGroup == wxString(PATH_SEP_REPLACE) || + m_strGroup.Last() != PATH_SEP_REPLACE) ); +} + +const wxString& wxIniConfig::GetPath() const +{ + static wxString s_str; + + // always return abs path + s_str = wxCONFIG_PATH_SEPARATOR; + + if ( m_strGroup == wxString(PATH_SEP_REPLACE) ) { + // we're at the root level, nothing to do + } + else { + s_str << m_strGroup; + if ( !m_strPath.IsEmpty() ) + s_str << wxCONFIG_PATH_SEPARATOR; + for ( const char *p = m_strPath; *p != '\0'; p++ ) { + s_str << (*p == PATH_SEP_REPLACE ? wxCONFIG_PATH_SEPARATOR : *p); + } + } + + return s_str; +} + +wxString wxIniConfig::GetPrivateKeyName(const wxString& szKey) const +{ + wxString strKey; + + if ( !m_strPath.IsEmpty() ) + strKey << m_strPath << PATH_SEP_REPLACE; + + strKey << szKey; + + return strKey; +} + +wxString wxIniConfig::GetKeyName(const wxString& szKey) const +{ + wxString strKey; + + if ( m_strGroup != wxString(PATH_SEP_REPLACE) ) + strKey << m_strGroup << PATH_SEP_REPLACE; + if ( !m_strPath.IsEmpty() ) + strKey << m_strPath << PATH_SEP_REPLACE; + + strKey << szKey; + + return strKey; +} + +// ---------------------------------------------------------------------------- +// enumeration +// ---------------------------------------------------------------------------- + +// not implemented +bool wxIniConfig::GetFirstGroup(wxString& str, long& lIndex) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +bool wxIniConfig::GetNextGroup (wxString& str, long& lIndex) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +bool wxIniConfig::GetFirstEntry(wxString& str, long& lIndex) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +bool wxIniConfig::GetNextEntry (wxString& str, long& lIndex) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +// ---------------------------------------------------------------------------- +// misc info +// ---------------------------------------------------------------------------- + +// not implemented +size_t wxIniConfig::GetNumberOfEntries(bool bRecursive) const +{ + wxFAIL_MSG("not implemented"); + + return (size_t)-1; +} + +size_t wxIniConfig::GetNumberOfGroups(bool bRecursive) const +{ + wxFAIL_MSG("not implemented"); + + return (size_t)-1; +} + +bool wxIniConfig::HasGroup(const wxString& strName) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +bool wxIniConfig::HasEntry(const wxString& strName) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +// is current group empty? +bool wxIniConfig::IsEmpty() const +{ + char szBuf[1024]; + +// GetPrivateProfileString(m_strGroup, NULL, "", +// szBuf, WXSIZEOF(szBuf), m_strLocalFilename); + if ( !::IsEmpty(szBuf) ) + return FALSE; + +// GetProfileString(m_strGroup, NULL, "", szBuf, WXSIZEOF(szBuf)); +// if ( !::IsEmpty(szBuf) ) + return FALSE; + + return TRUE; +} + +// ---------------------------------------------------------------------------- +// read/write +// ---------------------------------------------------------------------------- + +bool wxIniConfig::Read(const wxString& szKey, wxString *pstr) const +{ + wxConfigPathChanger path(this, szKey); + wxString strKey = GetPrivateKeyName(path.Name()); + + char szBuf[1024]; // @@ should dynamically allocate memory... + + // first look in the private INI file + + // NB: the lpDefault param to GetPrivateProfileString can't be NULL +// GetPrivateProfileString(m_strGroup, strKey, "", +// szBuf, WXSIZEOF(szBuf), m_strLocalFilename); + if ( ::IsEmpty(szBuf) ) { + // now look in win.ini + wxString strKey = GetKeyName(path.Name()); +// GetProfileString(m_strGroup, strKey, "", szBuf, WXSIZEOF(szBuf)); + } + + if ( ::IsEmpty(szBuf) ) { + return FALSE; + } + else { + *pstr = szBuf ; + return TRUE; + } +} + +bool wxIniConfig::Read(const wxString& szKey, wxString *pstr, + const wxString& szDefault) const +{ + wxConfigPathChanger path(this, szKey); + wxString strKey = GetPrivateKeyName(path.Name()); + + char szBuf[1024]; // @@ should dynamically allocate memory... + + // first look in the private INI file + + // NB: the lpDefault param to GetPrivateProfileString can't be NULL +// GetPrivateProfileString(m_strGroup, strKey, "", +// szBuf, WXSIZEOF(szBuf), m_strLocalFilename); + if ( ::IsEmpty(szBuf) ) { + // now look in win.ini + wxString strKey = GetKeyName(path.Name()); +// GetProfileString(m_strGroup, strKey, "", szBuf, WXSIZEOF(szBuf)); + } + + if ( ::IsEmpty(szBuf) ) { + *pstr = szDefault; + return FALSE; + } + else { + *pstr = szBuf ; + return TRUE; + } +} + +bool wxIniConfig::Read(const wxString& szKey, long *pl) const +{ + wxConfigPathChanger path(this, szKey); + wxString strKey = GetPrivateKeyName(path.Name()); + + // hack: we have no mean to know if it really found the default value or + // didn't find anything, so we call it twice + + static const int nMagic = 17; // 17 is some "rare" number + static const int nMagic2 = 28; // arbitrary number != nMagic + long lVal; // = GetPrivateProfileInt(m_strGroup, strKey, nMagic, m_strLocalFilename); + if ( lVal != nMagic ) { + // the value was read from the file + *pl = lVal; + return TRUE; + } + + // is it really nMagic? +// lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic2, m_strLocalFilename); + if ( lVal == nMagic2 ) { + // the nMagic it returned was indeed read from the file + *pl = lVal; + return TRUE; + } + + // no, it was just returning the default value, so now look in win.ini +// *pl = GetProfileInt(GetVendorName(), GetKeyName(szKey), *pl); + + return TRUE; +} + +bool wxIniConfig::Write(const wxString& szKey, const wxString& szValue) +{ + wxConfigPathChanger path(this, szKey); + wxString strKey = GetPrivateKeyName(path.Name()); + + bool bOk; // = WritePrivateProfileString(m_strGroup, strKey, +// szValue, m_strLocalFilename) != 0; + + if ( !bOk ) + wxLogLastError("WritePrivateProfileString"); + + return bOk; +} + +bool wxIniConfig::Write(const wxString& szKey, long lValue) +{ + // ltoa() is not ANSI :-( + char szBuf[40]; // should be good for sizeof(long) <= 16 (128 bits) + sprintf(szBuf, "%ld", lValue); + + return Write(szKey, szBuf); +} + +bool wxIniConfig::Flush(bool /* bCurrentOnly */) +{ + // this is just the way it works +// return WritePrivateProfileString(NULL, NULL, NULL, m_strLocalFilename) != 0; + return FALSE; +} + +// ---------------------------------------------------------------------------- +// delete +// ---------------------------------------------------------------------------- + +bool wxIniConfig::DeleteEntry(const wxString& szKey, bool bGroupIfEmptyAlso) +{ + // passing NULL as value to WritePrivateProfileString deletes the key +// if ( !Write(szKey, (const char *)NULL) ) +// return FALSE; + wxConfigPathChanger path(this, szKey); + wxString strKey = GetPrivateKeyName(path.Name()); + +// if (WritePrivateProfileString(m_strGroup, szKey, +// (const char*) NULL, m_strLocalFilename) == 0) +// return FALSE; + + if ( !bGroupIfEmptyAlso || !IsEmpty() ) + return TRUE; + + // delete the current group too + bool bOk; // = WritePrivateProfileString(m_strGroup, NULL, +// NULL, m_strLocalFilename) != 0; + + if ( !bOk ) + wxLogLastError("WritePrivateProfileString"); + + return bOk; +} + +bool wxIniConfig::DeleteGroup(const wxString& szKey) +{ + wxConfigPathChanger path(this, szKey); + + // passing NULL as section name to WritePrivateProfileString deletes the + // whole section according to the docs + bool bOk; // = WritePrivateProfileString(path.Name(), NULL, + // NULL, m_strLocalFilename) != 0; + + if ( !bOk ) + wxLogLastError("WritePrivateProfileString"); + + return bOk; +} + +#ifndef MAX_PATH +#define MAX_PATH 256 +#endif + +bool wxIniConfig::DeleteAll() +{ + // first delete our group in win.ini +// WriteProfileString(GetVendorName(), NULL, NULL); + + // then delete our own ini file + char szBuf[MAX_PATH]; + size_t nRc; // = GetWindowsDirectory(szBuf, WXSIZEOF(szBuf)); + if ( nRc == 0 ) + { + wxLogLastError("GetWindowsDirectory"); + } + else if ( nRc > WXSIZEOF(szBuf) ) + { + wxFAIL_MSG("buffer is too small for Windows directory."); + } + + wxString strFile = szBuf; + strFile << '\\' << m_strLocalFilename; + + if ( !wxRemoveFile(strFile) ) { + wxLogSysError(_("Can't delete the INI file '%s'"), strFile.c_str()); + return FALSE; + } + + return TRUE; +} + +bool wxIniConfig::RenameEntry(const wxString& oldName, const wxString& newName) +{ + // Not implemented + return FALSE; +} + +bool wxIniConfig::RenameGroup(const wxString& oldName, const wxString& newName) +{ + // Not implemented + return FALSE; +} diff --git a/src/os2/joystick.cpp b/src/os2/joystick.cpp index 6677277f48..5f20af8209 100644 --- a/src/os2/joystick.cpp +++ b/src/os2/joystick.cpp @@ -1,18 +1,22 @@ ///////////////////////////////////////////////////////////////////////////// // Name: joystick.cpp // Purpose: wxJoystick class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "joystick.h" -#endif +#include "wx/string.h" +#define INCL_PM +#include "os2.h" +#include "wx/os2/private.h" +#define NO_JOYGETPOSEX + +#include #include IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject) diff --git a/src/os2/listbox.cpp b/src/os2/listbox.cpp index 1dad21e12c..a3df98c3cf 100644 --- a/src/os2/listbox.cpp +++ b/src/os2/listbox.cpp @@ -1,31 +1,110 @@ /////////////////////////////////////////////////////////////////////////////// // Name: listbox.cpp // Purpose: wxListBox -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/09/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR +// Copyright: (c) David Webster // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "listbox.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" +#include "wx/window.h" +#include "wx/os2/private.h" + +#ifndef WX_PRECOMP #include "wx/listbox.h" #include "wx/settings.h" +#include "wx/brush.h" +#include "wx/font.h" +#include "wx/dc.h" +#include "wx/utils.h" +#endif + +#define INCL_M +#include + #include "wx/dynarray.h" #include "wx/log.h" +#if wxUSE_OWNER_DRAWN + #include "wx/ownerdrw.h" +#endif + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) #endif +// ============================================================================ +// list box item declaration and implementation +// ============================================================================ + +#if wxUSE_OWNER_DRAWN + +class wxListBoxItem : public wxOwnerDrawn +{ +public: + wxListBoxItem(const wxString& str = ""); +}; + +wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE) +{ + // no bitmaps/checkmarks + SetMarginWidth(0); +} + +wxOwnerDrawn *wxListBox::CreateItem(size_t n) +{ + return new wxListBoxItem(); +} + +#endif //USE_OWNER_DRAWN + // ============================================================================ // list box control implementation // ============================================================================ +bool wxListBox::OS2Command(WXUINT param, WXWORD WXUNUSED(id)) +{ +/* + if (param == LBN_SELCHANGE) + { + wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId); + wxArrayInt aSelections; + int count = GetSelections(aSelections); + if ( count > 0 ) + { + event.m_commandInt = aSelections[0] ; + event.m_clientData = GetClientData(event.m_commandInt); + wxString str(GetString(event.m_commandInt)); + if (str != wxT("")) + { + event.m_commandString = str; + } + } + else + { + event.m_commandInt = -1 ; + event.m_commandString.Empty(); + } + + event.SetEventObject( this ); + ProcessCommand(event); + return TRUE; + } + else if (param == LBN_DBLCLK) + { + wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId); + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent(event) ; + return TRUE; + } +*/ + return FALSE; +} // Listbox item wxListBox::wxListBox() { @@ -42,6 +121,7 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id, const wxString& name) { m_noItems = n; + m_hWnd = 0; m_selected = 0; SetName(name); @@ -51,92 +131,285 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id, wxSystemSettings settings; SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + SetForegroundColour(parent->GetForegroundColour()); m_windowId = ( id == -1 ) ? (int)NewControlId() : id; + int x = pos.x; + int y = pos.y; + int width = size.x; + int height = size.y; + m_windowStyle = style; + // TODO create listbox +/* + DWORD wstyle = WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | + LBS_NOTIFY | LBS_HASSTRINGS; + if (m_windowStyle & wxLB_MULTIPLE) + wstyle |= LBS_MULTIPLESEL; + else if (m_windowStyle & wxLB_EXTENDED) + wstyle |= LBS_EXTENDEDSEL; + + if (m_windowStyle & wxLB_ALWAYS_SB) + wstyle |= LBS_DISABLENOSCROLL ; + if (m_windowStyle & wxLB_HSCROLL) + wstyle |= WS_HSCROLL; + if (m_windowStyle & wxLB_SORT) + wstyle |= LBS_SORT; + +#if wxUSE_OWNER_DRAWN + if ( m_windowStyle & wxLB_OWNERDRAW ) { + // we don't support LBS_OWNERDRAWVARIABLE yet + wstyle |= LBS_OWNERDRAWFIXED; + } +#endif + + // Without this style, you get unexpected heights, so e.g. constraint layout + // doesn't work properly + wstyle |= LBS_NOINTEGRALHEIGHT; + + bool want3D; + WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ; + + // Even with extended styles, need to combine with WS_BORDER + // for them to look right. + if ( want3D || wxStyleHasBorder(m_windowStyle) ) + { + wstyle |= WS_BORDER; + } + + m_hWnd = (WXHWND)::CreateWindowEx(exStyle, wxT("LISTBOX"), NULL, + wstyle | WS_CHILD, + 0, 0, 0, 0, + (HWND)parent->GetHWND(), (HMENU)m_windowId, + wxGetInstance(), NULL); + +#if wxUSE_CTL3D + if (want3D) + { + Ctl3dSubclassCtl(GetHwnd()); + m_useCtl3D = TRUE; + } +#endif + + // Subclass again to catch messages + SubclassWin(m_hWnd); + + size_t ui; + for (ui = 0; ui < (size_t)n; ui++) { + Append(choices[ui]); + } + + if ( (m_windowStyle & wxLB_MULTIPLE) == 0 ) + SendMessage(GetHwnd(), LB_SETCURSEL, 0, 0); + + SetFont(parent->GetFont()); + + SetSize(x, y, width, height); + + Show(TRUE); +*/ return FALSE; } wxListBox::~wxListBox() { +#if wxUSE_OWNER_DRAWN + size_t uiCount = m_aItems.Count(); + while ( uiCount-- != 0 ) { + delete m_aItems[uiCount]; + } +#endif // wxUSE_OWNER_DRAWN +} + +void wxListBox::SetupColours() +{ + SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + SetForegroundColour(GetParent()->GetForegroundColour()); } void wxListBox::SetFirstItem(int N) { - // TODO + wxCHECK_RET( N >= 0 && N < m_noItems, + wxT("invalid index in wxListBox::SetFirstItem") ); + + // TODO SendMessage(GetHwnd(),LB_SETTOPINDEX,(WPARAM)N,(LPARAM)0) ; } void wxListBox::SetFirstItem(const wxString& s) { - // TODO + int N = FindString(s) ; + + if ( N >= 0 ) + SetFirstItem(N) ; } void wxListBox::Delete(int N) { - m_noItems --; - // TODO + wxCHECK_RET( N >= 0 && N < m_noItems, + wxT("invalid index in wxListBox::Delete") ); + + // TODO SendMessage(GetHwnd(), LB_DELETESTRING, N, 0); + m_noItems --; + SetHorizontalExtent(""); } void wxListBox::Append(const wxString& item) { - m_noItems ++; + int index=0; // TODO = ListBox_AddString(GetHwnd(), item); + m_noItems ++; - // TODO +#if wxUSE_OWNER_DRAWN + if ( m_windowStyle & wxLB_OWNERDRAW ) { + wxOwnerDrawn *pNewItem = CreateItem(index); // dummy argument + pNewItem->SetName(item); + m_aItems.Add(pNewItem); +// ListBox_SetItemData(GetHwnd(), index, pNewItem); + } +#endif + + SetHorizontalExtent(item); } -void wxListBox::Append(const wxString& item, char *Client_data) +void wxListBox::Append(const wxString& item, void *Client_data) { - m_noItems ++; + int index; // TODO = ListBox_AddString(GetHwnd(), item); + m_noItems ++; - // TODO +#if wxUSE_OWNER_DRAWN + if ( m_windowStyle & wxLB_OWNERDRAW ) { + // client data must be pointer to wxOwnerDrawn, otherwise we would crash + // in OnMeasure/OnDraw. + wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes")); + } + else +#endif + + // TODO ListBox_SetItemData(GetHwnd(), index, Client_data); + + SetHorizontalExtent(item); } void wxListBox::Set(int n, const wxString *choices, char** clientData) { - m_noItems = n; +// ShowWindow(GetHwnd(), SW_HIDE); +// ListBox_ResetContent(GetHwnd()); + int i; + for (i = 0; i < n; i++) + { +// ListBox_AddString(GetHwnd(), choices[i]); +// if ( clientData ) +// ListBox_SetItemData(GetHwnd(), i, clientData[i]); + } + m_noItems = n; - // TODO +#if wxUSE_OWNER_DRAWN + if ( m_windowStyle & wxLB_OWNERDRAW ) { + // first delete old items + size_t ui = m_aItems.Count(); + while ( ui-- != 0 ) { + delete m_aItems[ui]; + } + m_aItems.Empty(); + + // then create new ones + for (ui = 0; ui < (size_t)n; ui++) { + wxOwnerDrawn *pNewItem = CreateItem(ui); + pNewItem->SetName(choices[ui]); + m_aItems.Add(pNewItem); +// ListBox_SetItemData(GetHwnd(), ui, pNewItem); + + wxASSERT_MSG(clientData[ui] == NULL, + wxT("Can't use client data with owner-drawn listboxes")); + } + } +#endif + + SetHorizontalExtent(""); +// ShowWindow(GetHwnd(), SW_SHOW); } int wxListBox::FindString(const wxString& s) const { - // TODO - return -1; + int pos; // = ListBox_FindStringExact(GetHwnd(), (WPARAM)-1, s); +// if (pos == LB_ERR) +// return -1; +// else + return pos; } void wxListBox::Clear() { - m_noItems = 0; - // TODO +// ListBox_ResetContent(GetHwnd()); + +#if wxUSE_OWNER_DRAWN + size_t uiCount = m_aItems.Count(); + while ( uiCount-- != 0 ) { + delete m_aItems[uiCount]; + } + + m_aItems.Clear(); +#endif // wxUSE_OWNER_DRAWN + + m_noItems = 0; +// ListBox_GetHorizontalExtent(GetHwnd()); } void wxListBox::SetSelection(int N, bool select) { - // TODO + wxCHECK_RET( N >= 0 && N < m_noItems, + wxT("invalid index in wxListBox::SetSelection") ); + + if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED)) + { +// SendMessage(GetHwnd(), LB_SETSEL, select, N); + } + else + { + int N1 = N; + if (!select) + N1 = -1; +// SendMessage(GetHwnd(), LB_SETCURSEL, N1, 0); + } } bool wxListBox::Selected(int N) const { - // TODO + wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE, + wxT("invalid index in wxListBox::Selected") ); + +// return SendMessage(GetHwnd(), LB_GETSEL, N, 0) == 0 ? FALSE : TRUE; return FALSE; } void wxListBox::Deselect(int N) { - // TODO + wxCHECK_RET( N >= 0 && N < m_noItems, + wxT("invalid index in wxListBox::Deselect") ); + + if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED)) + { +// SendMessage(GetHwnd(), LB_SETSEL, FALSE, N); + } } -char *wxListBox::GetClientData(int N) const +void *wxListBox::GetClientData(int N) const { - // TODO + wxCHECK_MSG( N >= 0 && N < m_noItems, NULL, + wxT("invalid index in wxListBox::GetClientData") ); + +// return (void *)SendMessage(GetHwnd(), LB_GETITEMDATA, N, 0); return (char *)NULL; } -void wxListBox::SetClientData(int N, char *Client_data) +void wxListBox::SetClientData(int N, void *Client_data) { - // TODO + wxCHECK_RET( N >= 0 && N < m_noItems, + wxT("invalid index in wxListBox::SetClientData") ); + +// if ( ListBox_SetItemData(GetHwnd(), N, Client_data) == LB_ERR ) +// wxLogDebug(wxT("LB_SETITEMDATA failed")); } // Return number of selections and an array of selected integers @@ -144,59 +417,169 @@ int wxListBox::GetSelections(wxArrayInt& aSelections) const { aSelections.Empty(); -/* TODO if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED)) { - int no_sel = ?? - for ( int n = 0; n < no_sel; n++ ) - aSelections.Add(??); + int no_sel; // = ListBox_GetSelCount(GetHwnd()); + if (no_sel != 0) { + int *selections = new int[no_sel]; +// if ( ListBox_GetSelItems(GetHwnd(), no_sel, selections) == LB_ERR ) { +// wxFAIL_MSG(wxT("This listbox can't have single-selection style!")); +// } + + aSelections.Alloc(no_sel); + for ( int n = 0; n < no_sel; n++ ) + aSelections.Add(selections[n]); + + delete [] selections; + } return no_sel; } else // single-selection listbox { - aSelections.Add(??); +// aSelections.Add(ListBox_GetCurSel(GetHwnd())); return 1; } -*/ - return 0; } // Get single selection, for single choice list items int wxListBox::GetSelection() const { - // TODO + wxCHECK_MSG( !(m_windowStyle & wxLB_MULTIPLE) && + !(m_windowStyle & wxLB_EXTENDED), + -1, + wxT("GetSelection() can't be used with multiple-selection " + "listboxes, use GetSelections() instead.") ); + +// return ListBox_GetCurSel(GetHwnd()); return -1; } // Find string for position wxString wxListBox::GetString(int N) const { - // TODO - return wxString(""); + wxCHECK_MSG( N >= 0 && N < m_noItems, "", + wxT("invalid index in wxListBox::GetClientData") ); + +// int len = ListBox_GetTextLen(GetHwnd(), N); + + // +1 for terminating NUL + wxString result; +// ListBox_GetText(GetHwnd(), N, result.GetWriteBuf(len + 1)); + result.UngetWriteBuf(); + + return result; } -void wxListBox::SetSize(int x, int y, int width, int height, int sizeFlags) +// OS/2-PM-specific code to set the horizontal extent of the listbox, if +// necessary. If s is non-NULL, it's used to calculate the horizontal extent. +// Otherwise, all strings are used. +void wxListBox::SetHorizontalExtent(const wxString& s) { - // TODO -} +/* + // Only necessary if we want a horizontal scrollbar + if (!(m_windowStyle & wxHSCROLL)) + return; + TEXTMETRIC lpTextMetric; + if (s != wxT("")) + { + int existingExtent = (int)SendMessage(GetHwnd(), LB_GETHORIZONTALEXTENT, 0, 0L); + HDC dc = GetWindowDC(GetHwnd()); + HFONT oldFont = 0; + if (GetFont().Ok() && GetFont().GetResourceHandle()) + oldFont = (HFONT) ::SelectObject(dc, (HFONT) GetFont().GetResourceHandle()); + + GetTextMetrics(dc, &lpTextMetric); + SIZE extentXY; + ::GetTextExtentPoint(dc, (LPTSTR) (const wxChar *)s, s.Length(), &extentXY); + int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth); + + if (oldFont) + ::SelectObject(dc, oldFont); + + ReleaseDC(GetHwnd(), dc); + if (extentX > existingExtent) + SendMessage(GetHwnd(), LB_SETHORIZONTALEXTENT, LOWORD(extentX), 0L); + return; + } + else + { + int largestExtent = 0; + HDC dc = GetWindowDC(GetHwnd()); + HFONT oldFont = 0; + if (GetFont().Ok() && GetFont().GetResourceHandle()) + oldFont = (HFONT) ::SelectObject(dc, (HFONT) GetFont().GetResourceHandle()); + + GetTextMetrics(dc, &lpTextMetric); + int i; + for (i = 0; i < m_noItems; i++) + { + int len = (int)SendMessage(GetHwnd(), LB_GETTEXT, i, (LONG)wxBuffer); + wxBuffer[len] = 0; + SIZE extentXY; + ::GetTextExtentPoint(dc, (LPTSTR)wxBuffer, len, &extentXY); + int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth); + if (extentX > largestExtent) + largestExtent = extentX; + } + if (oldFont) + ::SelectObject(dc, oldFont); + + ReleaseDC(GetHwnd(), dc); + SendMessage(GetHwnd(), LB_SETHORIZONTALEXTENT, LOWORD(largestExtent), 0L); + } +*/ +} void wxListBox::InsertItems(int nItems, const wxString items[], int pos) { + wxCHECK_RET( pos >= 0 && pos <= m_noItems, + wxT("invalid index in wxListBox::InsertItems") ); + + int i; +// for (i = 0; i < nItems; i++) +// ListBox_InsertString(GetHwnd(), i + pos, items[i]); m_noItems += nItems; - // TODO + SetHorizontalExtent(wxT("")); } void wxListBox::SetString(int N, const wxString& s) { - // TODO + wxCHECK_RET( N >= 0 && N < m_noItems, + wxT("invalid index in wxListBox::SetString") ); + + int sel = -1; + if (!(m_windowStyle & wxLB_MULTIPLE) && !(m_windowStyle & wxLB_EXTENDED)) + sel = GetSelection(); + + void *oldData = wxListBox::GetClientData(N); + +// SendMessage(GetHwnd(), LB_DELETESTRING, N, 0); + + int newN = N; + if (N == (m_noItems - 1)) + newN = -1; + +// SendMessage(GetHwnd(), LB_INSERTSTRING, newN, (LPARAM) (const wxChar *)s); + if (oldData) + wxListBox::SetClientData(N, oldData); + + // Selection may have changed + if (sel >= 0) + SetSelection(sel); + +#if wxUSE_OWNER_DRAWN + if ( m_windowStyle & wxLB_OWNERDRAW ) + // update item's text + m_aItems[N]->SetName(s); +#endif //USE_OWNER_DRAWN } int wxListBox::Number () const { - return m_noItems; + return m_noItems; } // For single selection items only @@ -221,6 +604,35 @@ bool wxListBox::SetStringSelection (const wxString& s, bool flag) return FALSE; } +wxSize wxListBox::DoGetBestSize() +{ + // find the widest string + int wLine; + int wListbox = 0; + for ( int i = 0; i < m_noItems; i++ ) + { + wxString str(GetString(i)); + GetTextExtent(str, &wLine, NULL); + if ( wLine > wListbox ) + wListbox = wLine; + } + + // give it some reasonable default value if there are no strings in the + // list + if ( wListbox == 0 ) + wListbox = 100; + + // the listbox should be slightly larger than the widest string + int cx, cy; + wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); + + wListbox += 3*cx; + + int hListbox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)*(wxMax(m_noItems, 7)); + + return wxSize(wListbox, hListbox); +} + void wxListBox::Command (wxCommandEvent & event) { if (event.m_extraLong) @@ -233,3 +645,97 @@ void wxListBox::Command (wxCommandEvent & event) ProcessCommand (event); } +WXHBRUSH wxListBox::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, + WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +{ +/* +#if wxUSE_CTL3D + if ( m_useCtl3D ) + { + HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam); + return (WXHBRUSH) hbrush; + } +#endif + + if (GetParent()->GetTransparentBackground()) + SetBkMode((HDC) pDC, TRANSPARENT); + else + SetBkMode((HDC) pDC, OPAQUE); + + ::SetBkColor((HDC) pDC, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue())); + ::SetTextColor((HDC) pDC, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue())); + + wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID); + + // Note that this will be cleaned up in wxApp::OnIdle, if backgroundBrush + // has a zero usage count. + backgroundBrush->RealizeResource(); +*/ + wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID); + return (WXHBRUSH) backgroundBrush->GetResourceHandle(); +} + +MRESULT wxListBox::OS2WindowProc(HWND hwnd, WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +{ + return wxControl::OS2WindowProc(hwnd, nMsg, wParam, lParam); +} + +#if wxUSE_OWNER_DRAWN + +// drawing +// ------- + +// space beneath/above each row in pixels +// "standard" checklistbox use 1 here, some might prefer 2. 0 is ugly. +#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1) + +// the height is the same for all items +// TODO should be changed for LBS_OWNERDRAWVARIABLE style listboxes + +// NB: can't forward this to wxListBoxItem because LB_SETITEMDATA +// message is not yet sent when we get here! +bool wxListBox::OS2OnMeasure(WXMEASUREITEMSTRUCT *item) +{ + // only owner-drawn control should receive this message + wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE ); + +// MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item; + + wxDC dc; +// TODO: dc.SetHDC((WXHDC)CreateIC(wxT("DISPLAY"), NULL, NULL, 0)); + dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_ANSI_VAR_FONT)); + +// pStruct->itemHeight = dc.GetCharHeight() + 2*OWNER_DRAWN_LISTBOX_EXTRA_SPACE; +// pStruct->itemWidth = dc.GetCharWidth(); + + return TRUE; +} + +// forward the message to the appropriate item +bool wxListBox::OS2OnDraw(WXDRAWITEMSTRUCT *item) +{ + // only owner-drawn control should receive this message + wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE ); +/* + DRAWITEMSTRUCT *pStruct = (DRAWITEMSTRUCT *)item; + + long data = ListBox_GetItemData(GetHwnd(), pStruct->itemID); + + wxCHECK( data && (data != LB_ERR), FALSE ); + + wxListBoxItem *pItem = (wxListBoxItem *)data; + + wxDC dc; + dc.SetHDC((WXHDC)pStruct->hDC, FALSE); + wxRect rect(wxPoint(pStruct->rcItem.left, pStruct->rcItem.top), + wxPoint(pStruct->rcItem.right, pStruct->rcItem.bottom)); + + return pItem->OnDrawItem(dc, rect, + (wxOwnerDrawn::wxODAction)pStruct->itemAction, + (wxOwnerDrawn::wxODStatus)pStruct->itemState); +*/ + return FALSE; +} + +#endif + // wxUSE_OWNER_DRAWN diff --git a/src/os2/makefile.va b/src/os2/makefile.va index ed81b2aea9..8dfa5ffbdb 100644 --- a/src/os2/makefile.va +++ b/src/os2/makefile.va @@ -67,6 +67,12 @@ $(CPPFLAGS) /Fo$@ /Tp $< $(CPPFLAGS) /Fo$@ /Tp $< << +{..\os2}.c{..\os2\$D}.obj: + @echo $< + icc @<< +$(CPPFLAGS) /Fo$@ /Tp $< +<< + {..\html}.cpp{..\html\$D}.obj: @echo $< icc @<< @@ -313,6 +319,13 @@ OS2OBJS = \ ..\os2\$D\frame.obj \ ..\os2\$D\gauge.obj \ ..\os2\$D\gdiobj.obj \ + ..\os2\$D\gsocket.obj \ + ..\os2\$D\helpwin.obj \ + ..\os2\$D\icon.obj \ + ..\os2\$D\imaglist.obj \ + ..\os2\$D\iniconf.obj \ + ..\os2\$D\joystick.obj \ + ..\os2\$D\listbox.obj \ ..\os2\$D\window.obj @@ -347,6 +360,13 @@ OS2LIBOBJS = \ frame.obj \ gauge.obj \ gdiobj.obj \ + gsocket.obj \ + helpwin.obj \ + icon.obj \ + imaglist.obj \ + iniconf.obj \ + joystick.obj \ + listbox.obj \ window.obj HTMLOBJS = \ @@ -524,6 +544,13 @@ $(OS2LIBOBJS): copy ..\os2\$D\frame.obj copy ..\os2\$D\gauge.obj copy ..\os2\$D\gdiobj.obj + copy ..\os2\$D\gsocket.obj + copy ..\os2\$D\helpwin.obj + copy ..\os2\$D\icon.obj + copy ..\os2\$D\imaglist.obj + copy ..\os2\$D\iniconf.obj + copy ..\os2\$D\joystick.obj + copy ..\os2\$D\listbox.obj copy ..\os2\$D\window.obj # wxWindows library as DLL