bool cCardClientRadegast::Login(void) { Logout(); if(!so.Connect(hostname,port)) return false; PRINTF(L_CC_LOGIN,"%s: connected to %s:%d",name,hostname,port); InitVars(); unsigned char buff[512]; char hello[32]; snprintf(hello,sizeof(hello),"rdgd/vdr-sc-%s",ScVersion); StartMsg(buff,0x90); // RDGD_MSG_CLIENT_HELLO AddNano(buff,1,strlen(hello),(unsigned char *)hello); // RDGD_NANO_DESCR if(!Send(buff) || Recv(buff,sizeof(buff))<0) return false; if(buff[0]==0x91) { PRINTF(L_CC_RDGD,"got server hello, assuming V4 mode"); StartMsg(buff,0x94); // RDGD_MSG_CLIENT_CAP_REQ; int n; if(!Send(buff) || (n=Recv(buff,sizeof(buff)))<0) return false; if(buff[0]==0x95) { LBSTARTF(L_CC_LOGIN); LBPUT("radegast: got caps"); int caid; for(int l=GetNanoStart(buff); l<n; l+=buff[l+1]+2) { switch(buff[l]) { case 0xE2: LBPUT(" VERS %s",(char *)&buff[l+2]); break; case 0xE4: // CAP_NANO_CAID if(numCaids>=MAXCAIDS) { l=n; break; } //stop processing caid=(buff[l+2]<<8)+buff[l+3]; LBPUT(" CAID %04X",caid); caids[numCaids++]=caid; // XXX we should have EMM processing setup here, but as we don't // XXX get any ua/sa we cannot filter EMM anyways break; case 0xE5: // CAP_NANO_PROVID for(int i=0; i<buff[l+1]; i+=3) LBPUT("/%02X%02X%02X",buff[l+2+i],buff[l+2+i+1],buff[l+2+i+2]); break; } } LBEND(); } } else PRINTF(L_CC_RDGD,"no server hello, assuming old mode"); if(emmProcessing && !emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name); CaidsChanged(); return true; }
static void PrintSetup(uint8_t SetupID,TRANSDUCER_SET *Setup) { StartMsg(); PrintStringP(PSTR("Setup ")); if( SetupID == -1 ) PrintStringP(PSTR(" (working)")); else { PrintD(SetupID,0); // == %d if( SetupID == CurrSetup ) PrintStringP(PSTR(" (current)")); } PrintStringP(PSTR(":\r\n")); PrintStringP(PSTR("Freq: ")); PrintD(Setup->Freq,5); PrintStringP(PSTR("Hz, ")); PrintD(Setup->Power,3); PrintStringP(PSTR(" Watts\r\n")); PrintStringP(PSTR("Output: ")); if( Setup->RunMode == RUN_CONTINUOUS ) PrintStringP(PSTR("Continuous\r\n")); else { PrintStringP(PSTR("Timed ")); PrintD(Setup->RunTimer,5); PrintCRLF(); } PrintStringP(PSTR("Control: ")); PrintStringP(CtlModeText[IDX_CTL_MODE(Setup->CtlMode)]); PrintInputMode(1,&Setup->Input1); PrintInputMode(2,&Setup->Input2); PrintCRLF(); }
static void PrintInputMode(uint8_t InputID,INPUT *Input) { StartMsg(); PrintStringP(PSTR("Mode I")); PrintChar('0' + InputID); PrintStringP(PSTR(": ")); PrintStringP(InputActionText[IDX_ACTION(Input->Action)]); if( Input->Print ) PrintStringP(PSTR(" +print")); }
bool cCardClientRadegast::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw) { cMutexLock lock(this); if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false; so.Flush(); int len=SCT_LEN(source); int keynr=-1; switch(ecm->caId>>8) { case 0x01: // Seca keynr=cParseSeca::KeyNr(source)&0x0F; break; case 0x05: // Viaccess keynr=cParseViaccess::KeyNr(source); break; case 0x18: // Nagra2 if(ecm->caId>=0x1801) keynr=(source[7]&0x10) | 0x86; break; } unsigned char buff[512], tmp[10]; StartMsg(buff,1); // CMD_ECM_KEY_ASK AddNano(buff,2,1,ecm->caId>>8); // ECM_NANO_CAID_INDEX (old) AddNano(buff,10,2,ecm->caId); // ECM_NANO_CAID sprintf((char *)tmp,"%08X",ecm->provId); AddNano(buff,6,8,tmp); // ECM_NANO_PROVIDER if(keynr>=0) { sprintf((char *)tmp,"%04X",keynr); AddNano(buff,7,4,tmp); // ECM_NANO_KEYNO } if(!CheckLength(buff,len)) return false; AddNano(buff,3,len,source); // ECM_NANO_PACKET if(!Send(buff) || (len=Recv(buff,sizeof(buff)))<0) return false; if(buff[0]==2) { for(int l=GetNanoStart(buff); l<len; l+=buff[l+1]+2) { switch(buff[l]) { case 0x05: if(buff[l+1]==16) { // check for zero cw, as someone may not send both cw's every time if(!CheckNull(buff+l+ 2,8)) memcpy(cw+0,buff+l+ 2,8); if(!CheckNull(buff+l+10,8)) memcpy(cw+8,buff+l+10,8); return true; } else PRINTF(L_CC_RDGD,"wrong cw length %d from server",buff[l+1]); break; case 0x04: PRINTF(L_CC_ECM,"%s: key not available from server",name); break; default: PRINTF(L_CC_RDGD,"unknown nano %02x in ECM response",buff[l]); break; } } } else PRINTF(L_CC_RDGD,"bad ECM response from server %02x != 02",buff[0]); return false; }
bool cCardClientRadegast::ProcessEMM(int caSys, const unsigned char *data) { if(emmProcessing && emmAllowed) { cMutexLock lock(this); int upd; cProvider *p; cAssembleData ad(data); if(MatchAndAssemble(&ad,&upd,&p)) { while((data=ad.Assembled())) { int len=SCT_LEN(data); int id=msEMM.Get(data,len,0); if(id>0 || emmAllowed>1) { unsigned char buff[512]; StartMsg(buff,0x41); // AddNano(buff,0x42,2,caSys); // EMM_CAID if(p) { unsigned char tmp[10]; sprintf((char *)tmp,"%08X",(int)p->ProvId()); AddNano(buff,0x46,8,tmp); // EMM_PROVID } /* if(upd==2 || upd==3) { AddNano(buff,0x44,2,(unsigned char *)"aa"); // EMM_ADDR_VAL } */ AddNano(buff,0x45,1,upd==3 ? 0x11 : (upd==2 ? 0x12 : 0x13)); // EMM_ADDR_TYPE if(CheckLength(buff,len)) { AddNano(buff,0x43,len,data); // EMM_CA_DATA Send(buff); } msEMM.Cache(id,true,0); } } return true; } } return false; }
int frmMain::ReconnectServer(pgServer *server, bool restore) { // Create a server object and connect it. wxBusyInfo waiting(wxString::Format(_("Connecting to server %s (%s:%d)"), server->GetDescription().c_str(), server->GetName().c_str(), server->GetPort()), this); // Give the UI a chance to redraw wxSafeYield(); wxMilliSleep(100); wxSafeYield(); int res = server->Connect(this, true); // Check the result, and handle it as appropriate wxTreeItemId item; switch (res) { case PGCONN_OK: { if (restore && server->GetRestore()) StartMsg(_("Restoring previous environment")); else StartMsg(_("Establishing connection")); wxLogInfo(wxT("pgServer object initialised as required.")); server->ShowTreeDetail(browser); browser->Freeze(); if (restore && server->GetRestore()) item=RestoreEnvironment(server); else item = server->GetId(); browser->Thaw(); if (item) { browser->SelectItem(item); wxSafeYield(); browser->Expand(item); browser->EnsureVisible(item); } if (item) EndMsg(true); else { if (restore && server->GetRestore()) EndMsg(false); else EndMsg(true); } if (item) GetMenuFactories()->CheckMenu((pgObject *)browser->GetItemData(item), GetMenuBar(), (ctlMenuToolbar *)GetToolBar()); else GetMenuFactories()->CheckMenu(server, GetMenuBar(), (ctlMenuToolbar *)GetToolBar()); return res; } case PGCONN_DNSERR: /* // looks strange to me. Shouldn_t server be removed from the tree as well? delete server; OnAddServer(wxCommandEvent()); break; */ case PGCONN_BAD: ReportConnError(server); break; default: wxLogInfo(wxT("pgServer object didn't initialise because the user aborted.")); break; } server->Disconnect(this); return res; }
void frmMain::Refresh(pgObject *data) { StartMsg(data->GetTranslatedMessage(REFRESHINGDETAILS)); browser->Freeze(); wxTreeItemId currentItem=data->GetId(); // Scan the child nodes and make a list of those that are expanded // This is not an exact science as node names may change etc. wxArrayString expandedNodes; GetExpandedChildNodes(currentItem, expandedNodes); browser->DeleteChildren(currentItem); // refresh information about the object data->SetDirty(); pgObject *newData = data->Refresh(browser, currentItem); bool done = !data->GetConnection() || data->GetConnection()->GetStatus() == PGCONN_OK; if (newData != data) { wxLogInfo(wxT("Deleting %s %s for refresh"), data->GetTypeName().c_str(), data->GetQuotedFullIdentifier().c_str()); if (data == currentObject) currentObject = newData; if (newData) { wxLogInfo(wxT("Replacing with new node %s %s for refresh"), newData->GetTypeName().c_str(), newData->GetQuotedFullIdentifier().c_str()); newData->SetId(currentItem); // not done automatically browser->SetItemData(currentItem, newData); // Update the node text if this is an object, as it may have been renamed if (!newData->IsCollection()) browser->SetItemText(currentItem, newData->GetDisplayName()); delete data; } else { wxLogInfo(wxT("No object to replace: vanished after refresh.")); // If the connection is dead, just return here if (data->GetConnection()->GetStatus() != PGCONN_OK) { CheckAlive(); browser->Thaw(); return; } wxTreeItemId delItem=currentItem; currentItem=browser->GetItemParent(currentItem); browser->SelectItem(currentItem); browser->Delete(delItem); } } if (currentItem) { execSelChange(currentItem, currentItem == browser->GetSelection()); // Attempt to expand any child nodes that were previously expanded ExpandChildNodes(currentItem, expandedNodes); } browser->Thaw(); EndMsg(done); }
bool SetupCmd(char *Command) { // // MO - Mode command // if( StrEQ(Command,"MO") ) { ModeCmd(ParseToken()); return true; } // // LS - Save setup // if( StrEQ(Command,"LS") ) { char *SetupText = ParseToken(); int SetupNum = atoi(SetupText); if( !strlen(SetupText) ) SetupNum = CurrSetup; LoadSetup(SetupNum); StartMsg(); PrintStringP(PSTR("Loaded setup ")); PrintD(CurrSetup,0); // == %d return true; } // // PS - Print current setup // if( StrEQ(Command,"PS") ) { char *SetupText = ParseToken(); int SetupNum = atoi(SetupText); if( !strlen(SetupText) ) PrintSetup(-1 ,&TransducerSet); else PrintSetup(SetupNum,&EEPROM.Setups[SetupNum].Setup); return true; } // // SS - Save current setup // if( StrEQ(Command,"SS") ) { char *SetupText = ParseToken(); int SetupNum = atoi(SetupText); if( !strlen(SetupText) ) SetupNum = CurrSetup; SaveSetup(SetupNum); StartMsg(); PrintStringP(PSTR("Saved as setup ")); PrintD(CurrSetup,SetupNum); // == %d return true; } return false; }
static void ModeCmd(char *Command) { // // Accept blank "MO" command as a request to print current mode // if( !strlen(Command) ) { StartMsg(); PrintStringP(PSTR("Current mode: ")); PrintStringP(CtlModeText[IDX_CTL_MODE(TransducerSet.CtlMode)]); return; } // // R - Set run mode // if( StrEQ(Command,"R") ) { StartMsg(); PrintStringP(PSTR("Run continuous")); TransducerRunMode(RUN_CONTINUOUS,0); return; } // // RT - Set timed run mode // if( StrEQ(Command,"RT") ) { char *TimeText = ParseToken(); int TimeTicks = atoi(TimeText); if( !strlen(TimeText) || TimeTicks < 0 ) { StartMsg(); PrintStringP(PSTR("Bad or out of range run time (")); PrintString(TimeText); PrintStringP(PSTR("), must be positive number.\r\n")); PrintStringP(PSTR("Type '?' for help\r\n")); return; } StartMsg(); PrintStringP(PSTR("Run for ")); PrintD(TimeTicks,0); PrintStringP(PSTR(" ticks.")); TransducerRunMode(RUN_TIMED,TimeTicks); return; } // // CF - Constant frequency // if( StrEQ(Command,"CF") ) { StartMsg(); PrintStringP(PSTR("Constant frequency mode")); TransducerCtlMode(CTL_CONST_FREQ); return; } // // Ix - Set input action // if( StrEQ(Command,"I1") || StrEQ(Command,"I2") ) { ModeInputCmd(Command[1] - '0',ParseToken()); return; } StartMsg(); PrintStringP(PSTR("Unrecognized mode argument (")); PrintString(Command); PrintStringP(PSTR(")\r\n")); PrintStringP(PSTR("Type '?' for help\r\n")); }
static void ModeInputCmd(uint8_t InputID,char *Command) { INPUT *Input; INPUT_ACTION Action; bool Print; // // Note - Caller will error if anything other than I1 or I2 is used. // if ( InputID == 1 ) Input = &TransducerSet.Input1; else Input = &TransducerSet.Input2; // // Accept blank "MO Ix" command as a request to print current mode // if( !strlen(Command) ) { PrintInputMode(InputID,Input); return; } bool ArgOK = false; // // U - Input is unused // if( StrEQ(Command,"U") ) { Action = INPUT_UNUSED; ArgOK = true; } // // XC - Input is unused // if( StrEQ(Command,"XC") ) { Action = INPUT_XCTRL; ArgOK = true; } // // PO - Input is unused // if( StrEQ(Command,"PO") ) { Action = INPUT_XPOPO; ArgOK = true; } // // ES - Input is unused // if( StrEQ(Command,"ES") ) { Action = INPUT_ESTOP; ArgOK = true; } StartMsg(); if( !ArgOK ) { PrintStringP(PSTR("Unrecognized input mode (")); PrintString(Command); PrintStringP(PSTR("), must be U, XC, PO, or ES.\r\n")); PrintStringP(PSTR("Type '?' for help\r\n")); return; } // // See if "P" appended to mode // Command = ParseToken(); Print = false; if( strlen(Command) > 0 ) { if( StrEQ(Command,"P") ) Print = true; else { PrintStringP(PSTR("Unrecognized input mode (")); PrintString(Command); PrintStringP(PSTR("), must be P or nothing.\r\n")); PrintStringP(PSTR("Type '?' for help\r\n")); return; } } Input->Action = Action; Input->Print = Print; PrintInputMode(InputID,Input); }
int Announce() { gr_list *fgr = NULL, *tmp; char *temp; FILE *fp; int Count = 0, rc = FALSE; int filepos, filepos1, filepos2; char group[13]; int i, groups, any; if (!do_quiet) { mbse_colour(CYAN, BLACK); printf("Announce new files\n"); } Uploads(); IsDoing("Announce files"); temp = calloc(PATH_MAX, sizeof(char)); snprintf(temp, PATH_MAX, "%s/etc/toberep.data", getenv("MBSE_ROOT")); if ((fp = fopen(temp, "r")) == NULL) { Syslog('+', "No new files to announce"); free(temp); if (!do_quiet) { printf(" No new files.\n"); } return FALSE; } if (!do_quiet) printf(" Preparing reports...\n"); while (fread(&T_File, sizeof(T_File), 1, fp) == 1) { if (T_File.Announce) { fill_grlist(&fgr, T_File.Group, T_File.Echo); Count++; } } fclose(fp); if (Count == 0) { unlink(temp); if (!do_quiet) printf(" No new files.\n"); Syslog('+', "No new files to announce"); free(temp); return FALSE; } if (!do_quiet) printf(" %d new files found\n", Count); sort_grlist(&fgr); /* * At this point we have a sorted list of groups with a counter * indicating howmany files to report in each group. */ snprintf(temp, PATH_MAX, "%s/etc/newfiles.data", getenv("MBSE_ROOT")); if ((fp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); if (!do_quiet) printf(" No newfile reports defined\n"); free(temp); return FALSE; } fread(&newfileshdr, sizeof(newfileshdr), 1, fp); groups = newfileshdr.grpsize / 13; while (fread(&newfiles, newfileshdr.recsize, 1, fp) == 1) { if (newfiles.Active) { filepos = ftell(fp); if (!do_quiet) printf(" %s\n", newfiles.Comment); any = FALSE; for (i = 0; i < groups; i++) { fread(&group, 13, 1, fp); for (tmp = fgr; tmp; tmp = tmp->next) if (strcmp(tmp->group, group) == 0) any = TRUE; } if (any) { fseek(fp, filepos, SEEK_SET); rc = TRUE; Syslog('+', "Create report: %s", newfiles.Comment); MsgCount = 1; if ((filepos1 = StartMsg()) != -1) { filepos2 = 0; while (fread(&group, 13, 1, fp) == 1) { for (tmp = fgr; tmp; tmp = tmp->next) { if (!strcmp(tmp->group, group)) { filepos2 = Report(tmp, filepos1); } } } FinishMsg(TRUE, filepos2); } } else { if (!do_quiet) printf(" No matching groups\n"); } fseek(fp, filepos, SEEK_SET); } fseek(fp, newfileshdr.grpsize, SEEK_CUR); } fclose(fp); tidy_grlist(&fgr); if (rc) { snprintf(temp, PATH_MAX, "%s/etc/toberep.data", getenv("MBSE_ROOT")); unlink(temp); } free(temp); return rc; }
int Report(gr_list *ta, int filepos) { FILE *fp, *fi; char *temp, *line; int i, Total = 0; unsigned int Size = 0; int filepos1 = 0, filepos2, filepos3 = 0, finalpos = 0; time_t ftime; temp = calloc(PATH_MAX, sizeof(char)); snprintf(temp, PATH_MAX, "%s/etc/toberep.data", getenv("MBSE_ROOT")); if ((fp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); return 0; } MacroVars("GJZ", "ssd", "", "", 0); MacroVars("slbkdt", "ssddss", "", "", 0, 0, "", ""); MacroVars("ABZ", "ddd", 0, 0, 0); while (fread(&T_File, sizeof(T_File), 1, fp) == 1) { if ((!strcmp(T_File.Echo, ta->echo)) && (!strcmp(T_File.Group, ta->group))) break; } Syslog('m', "Announce %s %s %s", T_File.Echo, T_File.Name, chartran(T_File.LName)); if ((fi = OpenMacro(newfiles.Template, newfiles.Language, FALSE)) != NULL) { /* * Area block header */ MacroVars("GJZ", "ssd", T_File.Echo, chartran(T_File.Comment), 0); fseek(fi, filepos, SEEK_SET); Msg_Macro(fi); filepos1 = ftell(fi); } else { free(temp); return 0; } fseek(fp, 0, SEEK_SET); while (fread(&T_File, sizeof(T_File), 1, fp) == 1) { if ((!strcmp(T_File.Echo, ta->echo)) && (!strcmp(T_File.Group, ta->group))) { if (CFG.slow_util && do_quiet) msleep(1); /* * Report one newfile, first line. */ fseek(fi, filepos1, SEEK_SET); ftime = T_File.Fdate; MacroVars("sl", "ss", T_File.Name, T_File.LName); MacroVars("bk", "dd", T_File.Size, T_File.SizeKb); MacroVars("dt", "ss", rfcdate(ftime), chartran(T_File.LDesc[0])); Msg_Macro(fi); filepos2 = ftell(fi); /* * Extra description lines follow */ for (i = 1; i < 24; i++) { fseek(fi, filepos2, SEEK_SET); if (strlen(T_File.LDesc[i])) { MacroVars("t", "s", chartran(T_File.LDesc[i])); Msg_Macro(fi); } else { line = calloc(MAXSTR, sizeof(char)); while ((fgets(line, MAXSTR-2, fi) != NULL) && ((line[0]!='@') || (line[1]!='|'))) {} free(line); } filepos3 = ftell(fi); } /* * Magic request */ if (strlen(T_File.Magic)) { MacroVars("u", "s", T_File.Magic); Msg_Macro(fi); } else { line = calloc(MAXSTR, sizeof(char)); while ((fgets(line, MAXSTR-2, fi) != NULL) && ((line[0]!='@') || (line[1]!='|'))) {} free(line); } filepos3 = ftell(fi); Total++; Size += T_File.SizeKb; } } /* * Area block footer */ if (Msg.Size > (CFG.new_split * 1024)) MacroVars("ABZ", "ddd", Total, Size, 1); else MacroVars("ABZ", "ddd", Total, Size, 0); fseek(fi, filepos3, SEEK_SET); Msg_Macro(fi); finalpos = ftell(fi); fclose(fp); free(temp); /* * Split messages if too big. */ if (Msg.Size > (CFG.new_split * 1024)) { MsgCount++; Syslog('m', "Report() splitting report"); FinishMsg(FALSE, finalpos); StartMsg(); } TotalFiles += Total; TotalSize += Size; if (fi != NULL) { fclose(fi); } return finalpos; }
int rinvoke(State *state, Object obj, int fn) { RemoteOpHeader h; u32 sb, sp = state->sp; int retc, argc; Node srv; Stream str; ConcreteType ct; regRoot(obj); regRoot(state); anticipateGC(64 * 1024); unregRoot(); unregRoot(); /* figure out where we're sending the invocation */ ct = CODEPTR(obj->flags); assert(!RESDNT(obj->flags)); srv = getLocFromObj(obj); /* figure out what object we're invoking on */ h.target = OIDOf(obj); if (isNoOID(h.target)) { ConcreteType ct = CODEPTR(obj->flags); printf("It was a %.*s\n", ct->d.name->d.items, ct->d.name->d.data); return debug(state, "Invoked object with no oid"); } assert(!isNoOID(h.target)); h.targetct = OIDOf(ct); /* push the header information */ h.kind = InvokeRequest; h.status = fn; h.option1 = retc = ct->d.opVector->d.data[fn]->d.nress; h.option2 = argc = ct->d.opVector->d.data[fn]->d.nargs; h.ss = OIDOf((Object)state); h.sslocation = myid; str = StartMsg(&h); state->nstoid = h.target; NewOID(&state->nsoid); TRACE(process, 5, ("Setting nsoid in state %#x to %s", state, OIDString(state->nsoid))); WriteOID(&state->nsoid, str); sb = sp - 8 * argc; TRACE(rinvoke, 3, ("Invoking on %#x %s a %.*s [%d] -> [%d]", obj, OIDString(h.target), ct->d.name->d.items, ct->d.name->d.data, argc, retc)); TRACE(rinvoke, 4, ("It is on node %s", NodeString(srv))); sendNVars(str, argc, (int *)sb, state->ep, state->et); state->sp = sb; inhibit_gc--; if (isLimbo(srv)) { findAndSendTo(h.target, str); } else { sendMsgTo(srv, str, h.target); } return 1; }
void frmMain::Refresh(pgObject *data) { bool done = false; pgObject *obj = NULL; StartMsg(data->GetTranslatedMessage(REFRESHINGDETAILS)); browser->Freeze(); wxTreeItemId currentItem = data->GetId(); if (currentItem) obj = browser->GetObject(currentItem); if (obj && obj->CheckOpenDialogs(browser, currentItem)) { wxString msg = _("There are properties dialogues open for one or more objects that would be refreshed. Please close the properties dialogues and try again."); wxMessageBox(msg, _("Cannot refresh browser"), wxICON_WARNING | wxOK); } else { if (data->GetMetaType() == PGM_SCHEMA && !data->IsCollection() && data->GetConnection()->BackendMinimumVersion(9, 3)) { // Event triggers backend functions are at schema level. // Hence, we can consider that Event Triggers at schema level and partly at database. // So, if any schema is refreshed, we need to the event trigger collection as well. // It's a special case, which effects the schema operations on the event triggers as well. // To solve this, we are navigating to the parent node (database node), and then locating event trigger collections. // Once we've found the event triggers collection, we refresh it. // wxTreeItemId dbItem = browser->GetItemParent(browser->GetItemParent(browser->GetSelection())); pgCollection *eventTrgCol = browser->FindCollection(eventTriggerFactory, dbItem); if(eventTrgCol) Refresh(eventTrgCol); } // Scan the child nodes and make a list of those that are expanded // This is not an exact science as node names may change etc. wxArrayString expandedNodes; GetExpandedChildNodes(currentItem, expandedNodes); browser->DeleteChildren(currentItem); // refresh information about the object data->SetDirty(); pgObject *newData = data->Refresh(browser, currentItem); done = !data->GetConnection() || data->GetConnection()->GetStatus() == PGCONN_OK; if (newData != data) { wxLogInfo(wxT("Deleting %s %s for refresh"), data->GetTypeName().c_str(), data->GetQuotedFullIdentifier().c_str()); if (data == currentObject) currentObject = newData; if (newData) { wxLogInfo(wxT("Replacing with new node %s %s for refresh"), newData->GetTypeName().c_str(), newData->GetQuotedFullIdentifier().c_str()); newData->SetId(currentItem); // not done automatically browser->SetItemData(currentItem, newData); // Update the node text if this is an object, as it may have been renamed if (!newData->IsCollection()) browser->SetItemText(currentItem, newData->GetDisplayName()); delete data; data = NULL; } else { wxLogInfo(wxT("No object to replace: vanished after refresh.")); // If the connection is dead, just return here if (data->GetConnection()->GetStatus() != PGCONN_OK) { CheckAlive(); browser->Thaw(); return; } wxTreeItemId delItem = currentItem; currentItem = browser->GetItemParent(currentItem); browser->SelectItem(currentItem); browser->Delete(delItem); } } if (currentItem) { // Select the current node execSelChange(currentItem, currentItem == browser->GetSelection()); // Attempt to expand any child nodes that were previously expanded ExpandChildNodes(currentItem, expandedNodes); } } browser->Thaw(); EndMsg(done); }