%% options copyright owner = Dirk Krause copyright year = 2016-xxxx license = bsd %% wx-gui type = frame contents = mainSizer icon = wxpqdic_icon status bar = 1 sTexts[8] menu bar = mbMain tool bar = tbMain [wxMenuBar mbMain] contents = menuFile contents = menuView contents = menuHelp [wxMenu menuFile] text = sTexts[0] contents = miFileExit [wxMenuItem miFileExit] id = WxpqdicFrame_Quit text = sTexts[1] tip = sTexts[2] [wxMenu menuView] text = sTexts[22] contents = miViewUpdate [wxMenuItem miViewUpdate] id = WxpqdicFrame_View_Update text = sTexts[23] tip = sTexts[24] [wxMenu menuHelp] text = sTexts[3] contents = miHelpAbout contents = miHelpContents [wxMenuItem miHelpAbout] id = WxpqdicFrame_Help_About text = sTexts[4] tip = sTexts[5] [wxMenuItem miHelpContents] id = WxpqdicFrame_Help_Contents text = sTexts[6] tip = sTexts[7] [wxBoxSizer mainSizer] direction = horizontal contents = $space(10) contents = verticalSizer contents = $space(10) [wxBoxSizer verticalSizer] direction = vertical grow = yes proportion = 1 contents = $space(10) contents = contentsSizer contents = $space(10) [wxGridBagSizer contentsSizer] grid = 2 2 contents = lLimit 0 0 1 1 right contents = tLimit . +1 1 1 contents = lUsed +1 0 1 1 right contents = tUsed . +1 1 1 contents = $space(5) +1 0 1 1 contents = lAccount +1 0 1 1 right contents = tAccount . +1 1 1 contents = $space(5) +1 0 1 1 contents = lAllowed +1 0 1 1 right contents = tAllowed . +1 1 1 contents = $space(5) +1 0 1 1 contents = lStatus +1 0 1 2 [wxStaticText lLimit] text = sTexts[13] [wxStaticText tLimit] text = sTexts[14] [wxStaticText lUsed] text = sTexts[15] [wxStaticText tUsed] text = sTexts[27] [wxStaticText lAccount] text = sTexts[17] [wxStaticText tAccount] text = sTexts[16] [wxStaticText lAllowed] text = sTexts[18] [wxStaticText tAllowed] text = sTexts[27] [wxStaticText lStatus] text = sTexts[21] [wxToolBar tbMain] contents = bUpdate contents = bExit [wxToolBarToolBase bUpdate] text = sTexts[25] tip = sTexts[24] bitmap = xpm_run_conversion id = WxpqdicFrame_View_Update [wxToolBarToolBase bExit] text = sTexts[26] tip = sTexts[2] bitmap = xpm_exit_program id = WxpqdicFrame_Quit %% header start %% class start class WxpqdicFrame : public Dk4WxFrame { private: /** Event table for frame. */ DECLARE_EVENT_TABLE() protected: /** Buffer for response processing. */ char bResponse[32 * sizeof(dk4_um_t)]; /** Address pair, 0=remote, 1=local. */ dk4_sockaddr_storage_t aAddresses[2]; /** Remote host name as wxChar string. */ wxString sHostname; /** Queue name as wxChar string. */ wxString sQueuename; /** User name as wxChar string. */ wxString sUsername; /** Localized texts. */ wxChar const * const *sTexts; /** Non-localized texts. */ wxChar const * const *sNlWx; /** Non-localized texts. */ dkChar const * const *sNlDk; /** Copy of the command line arguments poiner. */ wxChar **copyArgv; /* __CHANGE__ 011: Add further member variables. */ /** Critical section to protect socket and timer. */ wxCriticalSection csProtect; /** Black color for normal status text. */ wxColour cBlack; /** Red color for not allowed to print. */ wxColour cRed; /** Green color for allowed to print. */ wxColour cGreen; /** Timer for periodic updates. */ wxTimer timer; /** Error report from socket subsystem initialization. */ dk4_er_t sockerr; /** Host name to query. */ dkChar *pHostname; /** Print queue to check. */ char *pQueuename; /** User name to use in check. */ char *pUsername; /** Request to send to server. */ char *pRequest; /** Previous limit value. */ dk4_um_t uLimit; /** Previous used value. */ dk4_um_t uUsed; /** Previous account value. */ dk4_um_t uAccount; /** Length of request. */ size_t szRequest; /** Size of response buffer. */ size_t szResponse; /** Time last request was sended. */ dk4_time_t tRequestSended; /** Update interval in seconds. */ long lUpdateInterval; /** Timeout interval before complaining about missing response. */ long lWaitResponse; /** Previous summary value. */ int iSummary; /** Number of command line arguments. */ int copyArgc; /** Current state. */ int iState; /** Socket for data exchange */ dk4_socket_t sock; /** Port number on remote host. */ unsigned short usPortnumber; /** Local port number to use. */ unsigned short usLocalPort; /** Flag: Socket subsystem initialized. */ bool bSockInit; /** Flag: Remote host uses UTF-8 encoding (user name and queue name). */ bool bIsUtf8; /** Flag: This idle event is the first one (no idle events before). */ bool bFirstIdle; /** Flag: All components initialized completely. */ bool bIsInitialized; /** Flag: This is the first response. */ bool bFirstResponse; %% class end public: /** Constructor. @param wxid Window ID. @param applicationHelper Application helper object. @param hc Help controller for online help. @param argc Number of command line arguments. @param argv Command line arguments array. @param localizedTexts Localized wxChar texts. @param nlWx Non-localized wxChar texts. @param nlDk Non-localized dkChar texts. @param bSocketsInitialized Flag: Socket subsys initialized. @param psockerr Error report from socket initialization. */ WxpqdicFrame( int wxid, Dk4WxApplicationHelper *applicationHelper, Dk4WxHelpController *hc, int argc, wxChar **argv, wxChar const * const *localizedTexts, wxChar const * const *nlWx, dkChar const * const *nlDk, bool bSocketsInitialized, dk4_er_t *psockerr ); /** Destructor. */ ~WxpqdicFrame(); /** Check whether we can close the window. @param isLast Flag: Last main window to close. */ bool CanClose(bool isFinal); /** Handler for File/Exit. @param event Event to process. */ void OnQuit(wxCommandEvent & event); /** Handler for File/Update. @param event Event to process. */ void OnRun(wxCommandEvent & event); /** Handler for Help/About. @param event Event to process. */ void OnAbout(wxCommandEvent & event); /** Handler for Help/Contents. @param event Event to process. */ void OnHelpContents(wxCommandEvent & event); /* __CHANGE__ 008: Remove OnIdle if no idle processing required. */ /** Handler for idle events. */ void OnIdle(wxIdleEvent & event); /* __CHANGE__ 017: Event handlers for further events. */ /** Handler for timer event. @param event Timer event to process. */ void OnTimer(wxTimerEvent & event); /* __CHANGE__ 014: Add further methods. */ private: /** Attempt to configure. @param perrc Address of error code variable. @return True if configuration failed and the application should exit, false on success. */ bool ConfigureAndCheckNeedToClose(int *perrc); /** Attempt to receive data, send request again if interval is over. @return True if the windows requires an update, false otherwise. */ bool DataExchangeWithServer(void); bool RetrieveResponse(void); bool ProcessResponse(bool & found); bool SendRequest(bool force = false); }; %% header end %% module start #include "wxpqdic.h" #include "dk4user.h" #include "dk4enc.h" #include "dk4strd.h" #include "dk4rec.h" #include "dk4str8.h" #include "dk4strx.h" #include "dk4recwx.h" #include "dk4maasz.h" #include "dk4mai8ddu.h" #include "dk4mai8dii.h" #include "dk4mao8d.h" #include "dk4maowd.h" #include "dk4numco.h" #include "exit-program.xpm" #include "run-conversion.xpm" #include "dk4verswx.h" #if !defined(__WXMSW__) #include "dkicon.xpm" #endif $!trace-include /* __CHANGE__ 017: Add further events. */ /* __CHANGE__ 008: Remove OnIdle if no idle processing required. */ BEGIN_EVENT_TABLE(WxpqdicFrame, wxFrame) EVT_MENU(WxpqdicFrame_View_Update, WxpqdicFrame::OnRun) EVT_MENU(WxpqdicFrame_Quit, WxpqdicFrame::OnQuit) EVT_MENU(WxpqdicFrame_Help_About, WxpqdicFrame::OnAbout) EVT_MENU(WxpqdicFrame_Help_Contents, WxpqdicFrame::OnHelpContents) EVT_TIMER(WxpqdicFrame_Timer, WxpqdicFrame::OnTimer) EVT_IDLE(WxpqdicFrame::OnIdle) END_EVENT_TABLE() static const wxChar versionNumber[] = { DKT_VERSION_WX }; static const wxCmdLineEntryDesc wxpqdic_cmd_line_entries[] = { { wxCMD_LINE_OPTION, wxT_2("h"), wxT_2("host"), wxT_2("Host to connect to."), wxCMD_LINE_VAL_STRING, 0 }, { wxCMD_LINE_OPTION, wxT_2("p"), wxT_2("port"), wxT_2("Port number to connect to."), wxCMD_LINE_VAL_NUMBER, 0 }, { wxCMD_LINE_OPTION, wxT_2("l"), wxT_2("local-port"), wxT_2("Local port number to use."), wxCMD_LINE_VAL_NUMBER, 0 }, { wxCMD_LINE_OPTION, wxT_2("q"), wxT_2("queue"), wxT_2("Queue name to check."), wxCMD_LINE_VAL_STRING, 0 }, { wxCMD_LINE_OPTION, wxT_2("u"), wxT_2("user"), wxT_2("User name to check."), wxCMD_LINE_VAL_STRING, 0 }, { wxCMD_LINE_OPTION, wxT_2("i"), wxT_2("interval"), wxT_2("Time interval for automatic update."), wxCMD_LINE_VAL_NUMBER, 0 }, { wxCMD_LINE_OPTION, wxT_2("a"), wxT_2("ascii"), wxT_2("Remote host uses ASCII encoding, not UTF-8."), wxCMD_LINE_VAL_NONE, 0 }, { wxCMD_LINE_NONE } }; /** Key names for preferences. */ static const wxChar * const wxpqdic_pref_key_names[] = { $!string-table macro=wxT printqd.host printqd.port printqd.queue printqd.interval printqd.local printqd.encoding $!end }; /** Constant 8-bit strings, not localized. */ static const char * const wxpqdic_kw[] = { $!string-table # # 0 newline # \n # # 1 space # # # 2 keyword info # info $!end }; %% constructor start WxpqdicFrame::WxpqdicFrame( int wxid, Dk4WxApplicationHelper *applicationHelper, Dk4WxHelpController *hc, int argc, wxChar **argv, wxChar const * const *localizedTexts, wxChar const * const *nlWx, dkChar const * const *nlDk, bool bSocketsInitialized, dk4_er_t *psockerr ) : Dk4WxFrame(nlWx[0], applicationHelper, hc, wxid), sHostname(wxT("")), sQueuename(wxT("")), sUsername(wxT("")), cBlack(0, 0, 0), cRed(127, 0, 0), cGreen(0, 127, 0), timer(this, WxpqdicFrame_Timer) { /* __CHANGE__ 012: Add further local variables. */ /* __CHANGE__ 012: Initialize further local variables. */ sTexts = localizedTexts; sNlWx = nlWx; sNlDk = nlDk; #if defined(__WXMSW__) wxIcon wxpqdic_icon(sNlWx[4]); #else wxIcon wxpqdic_icon(xpm_dkicon); #endif /* __CHANGE__ 011: Initialize further class members. */ bSockInit = bSocketsInitialized; DK4_MEMCPY(&sockerr, psockerr, sizeof(dk4_er_t)); pHostname = NULL; pQueuename = NULL; pUsername = NULL; pRequest = NULL; szRequest = (size_t)0UL; lUpdateInterval = 30L; lWaitResponse = 1L; usPortnumber = 9100; usLocalPort = 9100; bIsUtf8 = true; bFirstIdle = true; bFirstResponse = true; bIsInitialized = false; copyArgc = argc; copyArgv = argv; sock = INVALID_SOCKET; iState = WXPQDIC_STATE_OK; tRequestSended = (dk4_time_t)0UL; szResponse = sizeof(bResponse); DK4_MEMRES(&(aAddresses[0]), (2*sizeof(dk4_sockaddr_storage_t))); %% constructor end if(dkctGUILayoutOK) { SetTitle(nlWx[0]); } /* __CHANGE__ 012: Release resources allocated by local variables. */ } %% module end WxpqdicFrame::~WxpqdicFrame() { /* __CHANGE__ 011: Release resources allocated by further class members. */ } bool WxpqdicFrame::CanClose(bool isLast) { bool back = true; return back; } void WxpqdicFrame::OnQuit(wxCommandEvent & event) { { wxCriticalSectionLocker lockCsProtect(csProtect); if (bIsInitialized) { timer.Stop(); bIsInitialized = false; } } if (INVALID_SOCKET != sock) { dk4socket_close(sock, NULL); sock = INVALID_SOCKET; } dk4mem_release(pUsername); dk4mem_release(pQueuename); dk4mem_release(pHostname); dk4mem_release(pRequest); Show(false); /* !!!!! TODO: Release resources */ Close(); } void WxpqdicFrame::OnAbout(wxCommandEvent & event) { wxString text(wxT("")); wxString title(wxT("")); /* Construct message text. */ text.Append(sNlWx[0]); text.Append(sNlWx[7]); #if 0 text.Append(sNlWx[1]); #endif text.Append(versionNumber); text.Append(sNlWx[8]); text.Append(sTexts[9]); text.Append(sNlWx[2]); text.Append(sNlWx[8]); text.Append(sNlWx[8]); text.Append(sTexts[11]); text.Append(sNlWx[8]); text.Append(sNlWx[9]); text.Append(sNlWx[8]); text.Append(sNlWx[8]); text.Append(sTexts[12]); text.Append(sNlWx[8]); text.Append(sNlWx[10]); text.Append(sNlWx[8]); text.Append(sNlWx[11]); text.Append(sNlWx[8]); text.Append(sNlWx[12]); text.Append(sNlWx[8]); text.Append(sNlWx[13]); text.Append(sNlWx[8]); text.Append(sNlWx[14]); text.Append(sNlWx[8]); text.Append(sNlWx[15]); text.Append(sNlWx[8]); /* Construct dialog box title. */ title.Append(sTexts[10]); title.Append(sNlWx[0]); /* Show dialog box. */ wxMessageBox(text, title); } void WxpqdicFrame::OnHelpContents(wxCommandEvent & event) { DisplayContents(); } /* __CHANGE__ 017: Event handlers for further events. */ /* __CHANGE__ 014: Implementation of further methods. */ bool WxpqdicFrame::ConfigureAndCheckNeedToClose(int *perrc) { dkChar buf[1024]; char c8b[1024]; dk4_er_t er; wxChar *pv[] = { NULL, NULL, NULL, NULL, NULL, NULL }; const wxChar *cptr; const size_t szbuf = DK4_SIZEOF(buf,dkChar); const size_t szc8b = sizeof(c8b); long l = 0L; int res = 0; bool back = true; /* Retrieve some fallback values from preferences. */ pAppHelp->GetMultiple(wxpqdic_pref_key_names, pv, 6); $? ". host = \"%!ws\"", TR_WXSTR(pv[0]) $? ". port = \"%!ws\"", TR_WXSTR(pv[1]) $? ". queue = \"%!ws\"", TR_WXSTR(pv[2]) $? ". interval = \"%!ws\"", TR_WXSTR(pv[3]) $? ". local = \"%!ws\"", TR_WXSTR(pv[4]) $? ". encoding = \"%!ws\"", TR_WXSTR(pv[5]) /* Check command line arguments */ { wxLogNull log; wxCmdLineParser parser(wxpqdic_cmd_line_entries, copyArgc, copyArgv); res = parser.Parse(false); /* Check overall parsing of arguments */ if (0 != res) { $? "! failed to parse cmd line args" /* ERROR: Failed to parse command line arguments */ *perrc = WXPQDIC_FRAME_ERROR_PARSE; goto finished; } /* Option -a means the remote host wants ASCII data. */ if (parser.Found(wxT_2("a"))) { bIsUtf8 = false; } else { if (NULL != pv[5]) { if (0 != dk4strx_casecmp(pv[5], sNlWx[16])) { if (0 != dk4strx_casecmp(pv[5], sNlWx[17])) { bIsUtf8 = false; } } } } /* Try to obtain host name from arguments or from preferences. */ dk4error_init(&er); cptr = NULL; if (parser.Found(wxT_2("h"), &sHostname)) { cptr = sHostname.c_str(); } else { cptr = pv[0]; } if (NULL != cptr) { if (pAppHelp->StringToDk(buf, szbuf, cptr, &er)) { pHostname = dk4str_dup(buf, NULL); if (NULL == pHostname) { $? ". pHostname = \"%!ds\"", pHostname /* ERROR: Memory */ *perrc = WXPQDIC_FRAME_ERROR_MEMORY; goto finished; } } else { /* ERROR: Failed to convert string */ *perrc = WXPQDIC_FRAME_ERROR_STRCONV_HOSTNAME; goto finished; } } if (NULL == pHostname) { /* ERROR: Missing host name */ *perrc = WXPQDIC_FRAME_ERROR_HOSTNAME; goto finished; } /* Queue name is required. */ cptr = NULL; if (parser.Found(wxT_2("q"), &sQueuename)) { cptr = sQueuename.c_str(); } else { cptr = pv[2]; } if (NULL != cptr) { res = dk4recwx_wxchar_to_char( c8b, szc8b, ((bIsUtf8) ? (DK4_ENCODING_UTF8) : (DK4_ENCODING_ASCII)), cptr, pAppHelp->GetWxEncoding(), NULL ); if (0 != res) { pQueuename = dk4str8_dup(c8b, NULL); if (NULL == pQueuename) { $? ". pQueuename = \"%!8s\"", pQueuename /* ERROR: Memory */ *perrc = WXPQDIC_FRAME_ERROR_MEMORY; goto finished; } } else { /* ERROR: String conversion failed */ *perrc = WXPQDIC_FRAME_ERROR_STRCONV_QUEUENAME; goto finished; } } else { /* ERROR: Missing queue name */ *perrc = WXPQDIC_FRAME_ERROR_QUEUENAME; goto finished; } if (NULL == pQueuename) { /* ERROR: Missing queue name */ *perrc = WXPQDIC_FRAME_ERROR_QUEUENAME; goto finished; } /* Port number is optional. */ { bool portnoFound = false; l = 0L; if (parser.Found(wxT_2("p"), &l)) { portnoFound = true; } else { if (NULL != pv[1]) { wxString s(pv[1]); if (s.ToLong(&l, 0)) { portnoFound = true; } } } if (portnoFound) { if ((long)(USHRT_MAX) < l) { /* ERROR: Port number out of range */ *perrc = WXPQDIC_FRAME_ERROR_PORT_OOR; goto finished; } if (0L == l) { /* ERROR: Illegal port number 0 */ *perrc = WXPQDIC_FRAME_ERROR_PORT_ZERO; goto finished; } usPortnumber = (unsigned short)l; } } /* Local port number is optional. */ { bool portnoFound = false; l = 0L; if (parser.Found(wxT_2("l"), &l)) { portnoFound = true; } else { if (NULL != pv[4]) { wxString s(pv[4]); if (s.ToLong(&l, 0)) { portnoFound = true; } } } if (portnoFound) { if ((long)(USHRT_MAX) < l) { /* ERROR: Port number out of range */ *perrc = WXPQDIC_FRAME_ERROR_LOCALPORT_OOR; goto finished; } if (0L == l) { /* ERROR: Illegal port number 0 */ *perrc = WXPQDIC_FRAME_ERROR_LOCALPORT_ZERO; goto finished; } usLocalPort = (unsigned short)l; } } /* User name is optional, use current user by default. */ if (parser.Found(wxT_2("u"), &sUsername)) { res = dk4recwx_wxchar_to_char( c8b, szc8b, ((bIsUtf8) ? (DK4_ENCODING_UTF8) : (DK4_ENCODING_ASCII)), sUsername.c_str(), pAppHelp->GetWxEncoding(), NULL ); if (0 != res) { pUsername = dk4str8_dup(c8b, NULL); if (NULL == pUsername) { /* ERROR: Memory */ *perrc = WXPQDIC_FRAME_ERROR_MEMORY; goto finished; } } else { /* ERROR: Failed to convert user name */ *perrc = WXPQDIC_FRAME_ERROR_STRCONV_USERNAME; goto finished; } } else { res = dk4user_get_logname(buf, szbuf, 0, NULL); if (0 != res) { res = dk4recode_dk_to_any( c8b, szc8b, ((bIsUtf8) ? (DK4_ENCODING_UTF8) : (DK4_ENCODING_ASCII)), buf, pAppHelp->GetDkEncoding(), NULL ); if (0 != res) { pUsername = dk4str8_dup(c8b, NULL); if (NULL == pUsername) { /* ERROR: Memory */ *perrc = WXPQDIC_FRAME_ERROR_MEMORY; goto finished; } } else { /* ERROR: Failed to convert user name */ *perrc = WXPQDIC_FRAME_ERROR_STRCONV_USERNAME; goto finished; } } else { /* ERROR: User name not found! */ *perrc = WXPQDIC_FRAME_ERROR_USERNAME; goto finished; } } if (NULL == pUsername) { /* ERROR: No user name */ *perrc = WXPQDIC_FRAME_ERROR_USERNAME; goto finished; } /* Interval length is optional. */ { bool intervalFound = false; l = 0L; if (parser.Found(wxT_2("p"), &l)) { intervalFound = true; } else { if (NULL != pv[3]) { wxString s(pv[3]); if (s.ToLong(&l, 0)) { intervalFound = true; } } } if (intervalFound) { if (5L <= l) { lUpdateInterval = l; } else { lUpdateInterval = 5L; } } } /* Now build request */ dk4error_init(&er); szRequest = strlen(wxpqdic_kw[2]); szRequest = dk4ma_size_t_add(szRequest, dk4str8_len(pQueuename), &er); szRequest = dk4ma_size_t_add(szRequest, dk4str8_len(pUsername), &er); szRequest = dk4ma_size_t_add(szRequest, dk4str8_len(wxpqdic_kw[2]), &er); szRequest = dk4ma_size_t_add(szRequest, 4, &er); if (DK4_E_NONE == er.ec) { pRequest = dk4mem_new(char,szRequest,NULL); if (NULL != pRequest) { if (0 == dk4str8_cpy_s(pRequest, szRequest, wxpqdic_kw[2], NULL)) { /* ERROR: BUG */ *perrc = WXPQDIC_FRAME_ERROR_BUG; goto finished; } if (0 == dk4str8_cat_s(pRequest, szRequest, wxpqdic_kw[1], NULL)) { /* ERROR: BUG */ *perrc = WXPQDIC_FRAME_ERROR_BUG; goto finished; } if (0 == dk4str8_cat_s(pRequest, szRequest, pQueuename, NULL)) { /* ERROR: BUG */ *perrc = WXPQDIC_FRAME_ERROR_BUG; goto finished; } if (0 == dk4str8_cat_s(pRequest, szRequest, wxpqdic_kw[1], NULL)) { /* ERROR: BUG */ *perrc = WXPQDIC_FRAME_ERROR_BUG; goto finished; } if (0 == dk4str8_cat_s(pRequest, szRequest, pUsername, NULL)) { /* ERROR: BUG */ *perrc = WXPQDIC_FRAME_ERROR_BUG; goto finished; } if (0 == dk4str8_cat_s(pRequest, szRequest, wxpqdic_kw[0], NULL)) { /* ERROR: BUG */ *perrc = WXPQDIC_FRAME_ERROR_BUG; goto finished; } szRequest = dk4str8_len(pRequest); $? ". request = \"%s\"", TR_8STR(pRequest) } else { /* ERROR: Memory */ *perrc = WXPQDIC_FRAME_ERROR_MEMORY; goto finished; } } else { /* ERROR: Numeric overflow in size calculation */ *perrc = WXPQDIC_FRAME_ERROR_SIZE_CALC_OVERFLOW; goto finished; } /* Create socket. */ sock = dk4socket_udp_client_for_host( aAddresses, pHostname, usPortnumber, usLocalPort, 1, NULL ); if (INVALID_SOCKET == sock) { *perrc = WXPQDIC_FRAME_ERROR_SOCKET; goto finished; } } $? ". successfully completed setup" tLimit->SetLabel(sTexts[27]); tUsed->SetLabel(sTexts[27]); tAccount->SetLabel(sTexts[27]); /* Finally indicate success. */ timer.Start(500); bIsInitialized = true; back = false; /* Clean up at end and return result. */ finished: pAppHelp->ReleaseWxcharStringArray(pv, 6); if (back) { if (INVALID_SOCKET != sock) { dk4socket_close(sock, NULL); sock = INVALID_SOCKET; } dk4mem_release(pUsername); dk4mem_release(pQueuename); dk4mem_release(pHostname); dk4mem_release(pRequest); } return back; } void WxpqdicFrame::OnIdle(wxIdleEvent & event) { int errorCode = WXPQDIC_FRAME_ERROR_NONE; bool mustClose = false; $? "+ OnIdle" /* __CHANGE__ */ { wxCriticalSectionLocker lockCsProtect(csProtect); if (bFirstIdle) { bFirstIdle = false; mustClose = ConfigureAndCheckNeedToClose(&errorCode); } } if (mustClose) { $? "! error in setup, must close window" const wxChar *ti; const wxChar *tx; ti = sTexts[58]; tx = sTexts[59]; switch (errorCode) { case WXPQDIC_FRAME_ERROR_PARSE : { ti = sTexts[30]; tx = sTexts[31]; } break; case WXPQDIC_FRAME_ERROR_MEMORY : { ti = sTexts[32]; tx = sTexts[33]; } break; case WXPQDIC_FRAME_ERROR_STRCONV_HOSTNAME : { ti = sTexts[34]; tx = sTexts[35]; } break; case WXPQDIC_FRAME_ERROR_HOSTNAME : { ti = sTexts[36]; tx = sTexts[37]; } break; case WXPQDIC_FRAME_ERROR_STRCONV_QUEUENAME : { ti = sTexts[38]; tx = sTexts[39]; } break; case WXPQDIC_FRAME_ERROR_QUEUENAME : { ti = sTexts[40]; tx = sTexts[41]; } break; case WXPQDIC_FRAME_ERROR_PORT_OOR : { ti = sTexts[42]; tx = sTexts[43]; } break; case WXPQDIC_FRAME_ERROR_PORT_ZERO : { ti = sTexts[42]; tx = sTexts[44]; } break; case WXPQDIC_FRAME_ERROR_STRCONV_USERNAME : { ti = sTexts[45]; tx = sTexts[46]; } break; case WXPQDIC_FRAME_ERROR_USERNAME : { ti = sTexts[47]; tx = sTexts[48]; } break; case WXPQDIC_FRAME_ERROR_LOCALPORT_OOR : { ti = sTexts[49]; tx = sTexts[50]; } break; case WXPQDIC_FRAME_ERROR_LOCALPORT_ZERO : { ti = sTexts[49]; tx = sTexts[51]; } break; case WXPQDIC_FRAME_ERROR_BUG : { ti = sTexts[52]; tx = sTexts[53]; } break; case WXPQDIC_FRAME_ERROR_SIZE_CALC_OVERFLOW : { ti = sTexts[54]; tx = sTexts[55]; } break; case WXPQDIC_FRAME_ERROR_SOCKET : { ti = sTexts[56]; tx = sTexts[57]; } break; } wxMessageBox(tx, ti, (wxICON_ERROR | wxOK), this); Show(false); Close(); } /* Allow idle handlers from the base class. */ $? "- OnIdle" event.Skip(); } void WxpqdicFrame::OnTimer(wxTimerEvent & event) { bool mustUpdate = false; $? "+ OnTimer" { wxCriticalSectionLocker lockCsProtect(csProtect); $? ". entered critical section" if (bIsInitialized) { $? ". already initialized" mustUpdate = DataExchangeWithServer(); } #if TRACE_DEBUG else { $? "! not yet initialized" } #endif $? ". exiting critical section" } if (mustUpdate) { Refresh(); Update(); } $? "- OnTimer" } bool WxpqdicFrame::ProcessResponse(bool & found) { wxChar wxb[16*sizeof(dk4_um_t)]; char *tokens[8]; /* Tokens in the response */ const char *ep; /* End part of text */ dk4_um_t limit; /* Print limit */ dk4_um_t used; /* Pages used with in limit */ dk4_um_t account; /* Personal account */ size_t sz; /* Number of tokens used */ size_t szwxb; /* Size of wxb */ int founddet; /* Details found. */ int res; /* Text to number conversion result */ int summary; /* Flag: Can print */ bool force; /* Flag: Force use of values */ bool back = false; $? "+ ProcessResponse" sz = dk4str8_tokenize(tokens, 8, bResponse, NULL, NULL); if (4 == sz) { $? ". 4 tokens" founddet = 0; force = bFirstResponse; switch (iState) { case WXPQDIC_STATE_TIMEOUT : case WXPQDIC_STATE_SEND_FAILED : { force = true; $? ". recover from error" } break; } $? ". force = %d", (force ? 1 : 0) if (0 == dk4str8_cmp("-1", tokens[0])) { $? ". 0 = unlimited" limit = DK4_UM_MAX; founddet |= 1; } else { limit = (dk4_um_t)0UL; ep = NULL; res = dk4ma_input_c8_dec_dk4_um_t(&limit, tokens[0], &ep, 1, NULL); if (0 != res) { $? ". 0 = %lu", (unsigned long)limit founddet |= 1; } #if TRACE_DEBUG else { $? "! 0 not a number" } #endif } used = (dk4_um_t)0UL; ep = NULL; res = dk4ma_input_c8_dec_dk4_um_t(&used, tokens[1], &ep, 1, NULL); if (0 != res) { $? ". 1 = %lu", (unsigned long)used founddet |= 2; } #if TRACE_DEBUG else { $? "! 1 not a number" } #endif account = (dk4_um_t)0UL; ep = NULL; res = dk4ma_input_c8_dec_dk4_um_t(&account, tokens[2], &ep, 1, NULL); if (0 != res) { $? ". 2 = %lu", (unsigned long)account founddet |= 4; } #if TRACE_DEBUG else { $? "! 2 not a number" } #endif summary = 0; ep = NULL; res = dk4ma_input_c8_dec_int(&summary, tokens[3], &ep, 1, NULL); if (0 != res) { $? ". 3 = %d", summary founddet |= 8; } #if TRACE_DEBUG else { $? "! 3 not a number" } #endif if (15 == (15 & founddet)) { $? ". processed successfully" /* Renew text labels */ #if DK4_SIZEOF_WXCHAR > 1 szwxb = DK4_SIZEOF(wxb,wxChar); if ((force) || (limit != uLimit)) { if (DK4_UM_MAX == limit) { tLimit->SetLabel(sTexts[14]); } else { res = dk4ma_write_wc_decimal_unsigned(wxb, szwxb, limit, 0, NULL); if (0 != res) { wxString s(wxb); tLimit->SetLabel(s); } } back = true; } if ((force) || (used != uUsed)) { res = dk4ma_write_wc_decimal_unsigned(wxb, szwxb, used, 0, NULL); if (0 != res) { wxString s(wxb); tUsed->SetLabel(s); } back = true; } if ((force) || (account != uAccount)) { res = dk4ma_write_wc_decimal_unsigned(wxb, szwxb, account, 0, NULL); if (0 != res) { wxString s(wxb); tAccount->SetLabel(s); } back = true; } #else if ((force) || (limit != uLimit)) { if (DK4_UM_MAX == limit) { tLimit->SetLabel(sTexts[14]); } else { wxString s(tokens[0]); tLimit->SetLabel(s); } back = true; $? ". update for limit" } if ((force) || (used != uUsed)) { wxString s(tokens[1]); tUsed->SetLabel(s); back = true; $? ". update for used" } if ((force) || (account != uAccount)) { wxString s(tokens[2]); tAccount->SetLabel(s); back = true; $? ". update for account" } #endif if ((force) || (summary != iSummary)) { wxString s(sTexts[(0 != summary) ? 19 : 20]); tAllowed->SetLabel(s); if (0 != summary) { tAllowed->SetForegroundColour(cGreen); } else { tAllowed->SetForegroundColour(cRed); } back = true; $? ". update for summary" } if (force) { lStatus->SetLabel(sNlWx[5]); switch (iState) { case WXPQDIC_STATE_TIMEOUT : case WXPQDIC_STATE_SEND_FAILED : { lStatus->SetForegroundColour(cBlack); } break; } } /* Save values for later comparisons */ uLimit = limit; uUsed = used; uAccount = account; iSummary = summary; bFirstResponse = false; /* Change state */ iState = WXPQDIC_STATE_OK; found = true; } #if TRACE_DEBUG else { $? "! processing failed" } #endif } #if TRACE_DEBUG else { $? "! not 4 tokens" } #endif $? "- ProcessResponse %d", ((back) ? (1) : (0)) return back; } bool WxpqdicFrame::RetrieveResponse(void) { dk4_sockaddr_storage_t remaddr; /* Source address */ size_t sz; /* Buffer size */ size_t szrema; /* Address size */ int res; /* Conversion result */ bool back = false; bool found = false; /* Flag: Found */ $? "+ RetrieveResponse" sz = szResponse; szrema = sizeof(remaddr); res = dk4socket_recvfrom( sock, bResponse, &sz, 0, (struct sockaddr *)(&remaddr), &szrema, 0L, 10000L, NULL ); switch (res) { case DK4_SOCKET_RESULT_SUCCESS : case DK4_SOCKET_RESULT_IN_PROGRESS : { $? ". data" if (0 < sz) { $? ". data length" bResponse[(szResponse > sz) ? (sz) : (szResponse - 1)] = '\0'; #if TRACE_DEBUG dk4str8_delnl(bResponse); $? ". response = \"%!8s\"", bResponse #endif if (1 /* ##### TODO: Compare addresses */ ) { $? ". addr ok" back = ProcessResponse(found); } #if TRACE_DEBUG else { $? "! addr mismatch" } #endif } #if TRACE_DEBUG else { $? "! data length 0" } #endif } break; default : { $? ". no data" } break; } if (!(found)) { if (WXPQDIC_STATE_SENDED == iState) { iState = WXPQDIC_STATE_TIMEOUT; tLimit->SetLabel(sTexts[27]); tUsed->SetLabel(sTexts[27]); tAccount->SetLabel(sTexts[27]); tAllowed->SetLabel(sTexts[27]); tAllowed->SetForegroundColour(cBlack); lStatus->SetLabel(sTexts[29]); lStatus->SetForegroundColour(cRed); back = true; } } $? "- RetrieveResponse %d", ((back) ? (1) : (0)) return back; } bool WxpqdicFrame::SendRequest(bool force) { dk4_time_t currenttime = (dk4_time_t)0UL; size_t sz = 0; int res = 0; bool mustsend = false; bool back = false; $? "+ SendRequest" if ((dk4_time_t)0UL == tRequestSended) { mustsend = true; } else { if (force) { mustsend = true; } else { dk4time_get(¤ttime); if ((tRequestSended + (dk4_time_t)lUpdateInterval) <= currenttime) { mustsend = true; } } } if (mustsend) { $? ". must send" sz = szRequest; if ((dk4_um_t)0UL == currenttime) { dk4time_get(¤ttime); } res = dk4socket_sendto( sock, pRequest, &sz, 0, (struct sockaddr *)(&(aAddresses[0])), sizeof(dk4_sockaddr_storage_t), 0L, 0L, NULL ); tRequestSended = currenttime; switch (res) { case DK4_SOCKET_RESULT_SUCCESS : case DK4_SOCKET_RESULT_IN_PROGRESS : { $? ". success, sended" switch (iState) { case WXPQDIC_STATE_OK : { iState = WXPQDIC_STATE_SENDED; } break; } } break; default : { $? "! send" if (WXPQDIC_STATE_SEND_FAILED != iState) { tLimit->SetLabel(sTexts[27]); tUsed->SetLabel(sTexts[27]); tAccount->SetLabel(sTexts[27]); tAllowed->SetLabel(sTexts[27]); lStatus->SetLabel(sTexts[28]); lStatus->SetForegroundColour(cRed); back = true; } iState = WXPQDIC_STATE_SEND_FAILED; } break; } } #if TRACE_DEBUG else { $? ". no need to send" } #endif $? "- SendRequest %d", ((back) ? (1) : (0)) return back; } void WxpqdicFrame::OnRun(wxCommandEvent & event) { bool mustUpdate = false; $? "+ OnRun" { wxCriticalSectionLocker lockCsProtect(csProtect); if (bIsInitialized) { mustUpdate = SendRequest(true); } } if (mustUpdate) { Refresh(); Update(); } $? "- OnRun" } bool WxpqdicFrame::DataExchangeWithServer(void) { bool back = false; $? "+ DataExchangeWithServer" if (RetrieveResponse()) { back = true; } if (SendRequest()) { back = true; } $? "- DataExchangeWithServer %d", ((back) ? (1) : (0)) return back; }