bool SymNode::cullNode2(){ debout("cn1"); if(t == BTERM){ return true; } //Keep in mind that the tree should already be in DNF assert(t == SAND && children.size() > 0); noDuplicateNodes(children); if(children.size() == 1){ debout("cn2"); assert((*children.begin())->t == BTERM); this->addChild(new SymNode(BTERM, ((*children.begin())->bt))); //this->t = (*children.begin())->t; //this->bt = (*children.begin())->bt; //(*children.begin())->destroyTree(); //children.clear(); return true; }else if (children.size() == 3) { debout("cn3"); // Modification by BK: inserted this case (8/1/2007) // if one of the children is UNKNOWN_LITERAL, then remove that literal int removedUnknown = false; CLIter it = children.begin(); while(it != children.end()){ assert((*it)->t == BTERM); CLIter e = it; it++; if ((*e)->bt == UNKNOWN_LITERAL){ removedUnknown = true; (*e)->destroyTree(); children.erase(e); } } if (!removedUnknown){ this->destroyTree(); return false; } }else if ( children.size()>3 ){ // Note: all the children will be distinct, due to noDuplicateNodes() debout("cn4"); this->destroyTree(); return false; }//Children size == 2 debout("cn4"); // Sort the 2-tuple CLIter one,two; one = two = children.begin(); two++; if( (*one)->bt > (*two)->bt ){ BTerm temp = (*two)->bt; (*two)->bt = (*one)->bt; (*one)->bt = temp; } return true; }
int SymTree::get_next_pair(int &a, int &b){ //Used to iterator over a culled tree //ready == 1 indicated just culled or able to give new node //ready == 0 means that there aren't any items left, the values for a,b are unchanged. if(ready == 1){ //printf("SymTree::get_next_pair()\n"); debout("g1"); if( root->t == SAND ){ debout("g1.1"); assert(root->children.size() == 2); CLIter childI = root->children.begin(); a = (*childI)->bt; childI++; b = (*childI)->bt; ready = 0; assert(a <= b); // BK: bug detection (8/7/2007) return 1; }else if(root->t == SOR){ debout("g1.2"); if((*curAnd)->t == BTERM){ a = b = (*curAnd)->bt; }else{ assert((*curAnd)->t == SAND); CLIter childI = (*curAnd)->children.begin(); a = (*childI)->bt; childI++; b = (*childI)->bt; } curAnd++; if(curAnd == root->children.end()){ ready = 0; } assert(a <= b); // BK: bug detection (8/7/2007) return 1; }else if(root->t == BTERM){ debout("g1.3"); a = b = root->bt; ready = 0; assert(a <= b); // BK: bug detection (8/7/2007) return 1; }else{ return 0; } }else if(ready == 0){ return 0; }else{//This was called after the tree was modified without culling cerr << "get_next_pair called without first calling cull. Status: "<<flush; cerr << ready << endl; assert(0); return ready; } }
void EvalDebugStop(const void *data, qCtx *ctx, qStr *out, qArgAry *args) { if (ctx->GetSafeMode()) {ctx->Throw(out, 301, "function not available"); return;} // apache environment only... should be GetDebugEnv(ctx) ... etc char *p; bool ok = true; char cmd[256]; qArgAry cmdArgs; qCtxTmp debCtx(ctx); qStrFileO debout(stdout); debCtx.MapObj(&ok, (QOBJFUNC) EvalBreak, "go"); printf("Press enter to continue\n"); while (ok && fgets(cmd, 255, stdin)) { p = cmd; while (*p && !isspace(*p) && *p != '(') ++p; *p++ = '\0'; if (cmd && *cmd) { qObj *obj; debCtx.Find(&obj, cmd); cmdArgs.Grow(0); qStrReadBuf rTmp(p); debCtx.ParseArgsQmap(&rTmp, &cmdArgs, obj->GetQmap()); debCtx.Eval(&debout, cmd, &cmdArgs); debout.PutC('\n'); } else break; } }
/* ReadMessage - display a window and read the current message * * arguments: * idoc idoc to read (-1 for 1st unread) * * return value: * TRUE (-1) read ok * FALSE (0) couldn't read file */ FLAG PASCAL INTERNAL ReadMessage ( INT idoc ) { PSTR pTmpFN; CHAR title [ MAXLINELEN ]; if ( idocLast != -1 ) { #if DEBUG debout ( "I'd read message %d if I could...", idoc ); #endif idoc = ( idoc == -1 ) ? NextUnread ( -1 ) : idoc; if ( idoc != -1 ) { if ( idoc > idocLast || idoc < 0 ) idoc = idocLast; pTmpFN = mktmpnam ( ); if ( IdocToFile ( idoc, pTmpFN, 0 ) != ERROR ) { sprintf ( title, "Message %d", idoc + 1 ); fAllowCM = TRUE; hReadMessage = ZmReadFile ( pTmpFN, title, TRUE, 0, 0, -xSize, HdrHeight, readProc, readSKey ); ChangeHeaderFlag ( idocRead = idoc, 0, F_UNREAD ); ZMfree ( pTmpFN ); return TRUE; } ZMfree ( pTmpFN ); } } return FALSE; }
void EvalDebugTrace(const void *data, qCtx *ctx, qStr *out, qArgAry *args) { if (ctx->GetSafeMode()) {ctx->Throw(out, 301, "function not available"); return;} // apache environment only... should be GetDebugEnv(ctx) ... etc qStrFileO debout(stdout); debout.PutS((*args)[0]); }
void SymNode::removeParens(){ // If child node has same type as parent, then we flatten the tree. CLIter cur = children.begin(); while( cur != children.end() ){ if((*cur)->t == t){ debout("removeParens simplifies"); this->addChildren(*cur); delete (*cur); cur = children.erase(cur); }else{ cur++; } } }
void vi() { REG int key; /* keystroke from user */ long count; /* numeric argument to some functions */ REG struct keystru *keyptr;/* pointer to vikeys[] element */ MARK tcurs; /* temporary cursor */ int prevkey;/* previous key, if d/c/y/</>/! */ MARK range; /* start of range for d/c/y/</>/! */ char text[132]; int dotkey; /* last "key" of a change */ int dotpkey;/* last "prevkey" of a change */ int dotkey2;/* last extra "getkey()" of a change */ int dotcnt; /* last "count" of a change */ int firstkey; REG int i; /* tell the redraw() function to start from scratch */ redraw(MARK_UNSET, FALSE); #ifdef lint /* lint says that "range" might be used before it is set. This * can't really happen due to the way "range" and "prevkey" are used, * but lint doesn't know that. This line is here ONLY to keep lint * happy. */ range = 0L; #endif /* safeguard against '.' with no previous command */ dotkey = dotpkey = dotkey2 = dotcnt = 0; /* go immediately into insert mode, if ":set inputmode" */ firstkey = 0; #ifndef NO_EXTENSIONS if (*o_inputmode) { firstkey = 'i'; } #endif /* Repeatedly handle VI commands */ for (count = 0, prevkey = '\0'; mode == MODE_VI; ) { /* if we've moved off the undoable line, then we can't undo it at all */ if (markline(cursor) != U_line) { U_line = 0L; } /* report any changes from the previous command */ if (rptlines >= *o_report) { redraw(cursor, FALSE); msg("%ld line%s %s", rptlines, (rptlines==1?"":"s"), rptlabel); } rptlines = 0L; /* get the next command key. It must be ASCII */ if (firstkey) { key = firstkey; firstkey = 0; } else { do { key = getkey(WHEN_VICMD); } while (key < 0 || key > 127); } #ifdef DEBUG2 debout("\nkey='%c'\n", key); #endif /* Convert a doubled-up operator such as "dd" into "d_" */ if (prevkey && key == prevkey) { key = '_'; } /* look up the structure describing this command */ keyptr = &vikeys[key]; /* '&' and uppercase operators always act like doubled */ if (!prevkey && keyptr->args == CURSOR_MOVED && (key == '&' || isupper(key))) { range = cursor; prevkey = key; key = '_'; keyptr = &vikeys[key]; } #ifndef NO_VISIBLE /* if we're in the middle of a v/V command, reject commands * that aren't operators or movement commands */ if (V_from && !(keyptr->flags & VIZ)) { beep(); prevkey = 0; count = 0; continue; } #endif /* if we're in the middle of a d/c/y/</>/! command, reject * anything but movement. */ if (prevkey && !(keyptr->flags & (MVMT|PTMV))) { beep(); prevkey = 0; count = 0; continue; } /* set the "dot" variables, if we're supposed to */ if (((keyptr->flags & SDOT) || (prevkey && vikeys[prevkey].flags & SDOT)) #ifndef NO_VISIBLE && !V_from #endif ) { dotkey = key; dotpkey = prevkey; dotkey2 = '\0'; dotcnt = count; /* remember the line before any changes are made */ if (U_line != markline(cursor)) { U_line = markline(cursor); strcpy(U_text, fetchline(U_line)); } } /* if this is "." then set other vars from the "dot" vars */ if (key == '.') { key = dotkey; keyptr = &vikeys[key]; prevkey = dotpkey; if (prevkey) { range = cursor; } if (count == 0) { count = dotcnt; } doingdot = TRUE; /* remember the line before any changes are made */ if (U_line != markline(cursor)) { U_line = markline(cursor); strcpy(U_text, fetchline(U_line)); } } else { doingdot = FALSE; } /* process the key as a command */ tcurs = cursor; force_flags = NO_FLAGS; switch (keyptr->args & ARGSMASK) { case ZERO: if (count == 0) { tcurs = cursor & ~(BLKSIZE - 1); break; } /* else fall through & treat like other digits... */ case DIGIT: count = count * 10 + key - '0'; break; case KEYWORD: /* if not on a keyword, fail */ pfetch(markline(cursor)); key = markidx(cursor); if (!isalnum(ptext[key])) { tcurs = MARK_UNSET; break; } /* find the start of the keyword */ while (key > 0 && isalnum(ptext[key - 1])) { key--; } tcurs = (cursor & ~(BLKSIZE - 1)) + key; /* copy it into a buffer, and NUL-terminate it */ i = 0; do { text[i++] = ptext[key++]; } while (isalnum(ptext[key])); text[i] = '\0'; /* call the function */ tcurs = (*keyptr->func)(text, tcurs, count); count = 0L; break; case NO_ARGS: if (keyptr->func) { (*keyptr->func)(); } else { beep(); } count = 0L; break; case CURSOR: tcurs = (*keyptr->func)(cursor, count, key, prevkey); count = 0L; break; case CURSOR_CNT_KEY: if (doingdot) { tcurs = (*keyptr->func)(cursor, count, dotkey2); } else { /* get a key */ i = getkey(KEYMODE(keyptr->args)); if (i == '\033') /* ESC */ { count = 0; tcurs = MARK_UNSET; break; /* exit from "case CURSOR_CNT_KEY" */ } else if (i == ctrl('V')) { i = getkey(0); } /* if part of an SDOT command, remember it */ if (keyptr->flags & SDOT || (prevkey && vikeys[prevkey].flags & SDOT)) { dotkey2 = i; } /* do it */ tcurs = (*keyptr->func)(cursor, count, i); } count = 0L; break; case CURSOR_MOVED: #ifndef NO_VISIBLE if (V_from) { range = cursor; tcurs = V_from; count = 0L; prevkey = key; key = (V_linemd ? 'V' : 'v'); keyptr = &vikeys[key]; } else #endif { prevkey = key; range = cursor; force_flags = LNMD|INCL; } break; case CURSOR_EOL: prevkey = key; /* a zero-length line needs special treatment */ pfetch(markline(cursor)); if (plen == 0) { /* act on a zero-length section of text */ range = tcurs = cursor; key = '0'; } else { /* act like CURSOR_MOVED with '$' movement */ range = cursor; tcurs = m_rear(cursor, 1L); key = '$'; } count = 0L; keyptr = &vikeys[key]; break; case CURSOR_TEXT: do { text[0] = key; text[1] = '\0'; if (doingdot || vgets(key, text + 1, sizeof text - 1) >= 0) { /* reassure user that <CR> was hit */ qaddch('\r'); refresh(); /* call the function with the text */ tcurs = (*keyptr->func)(cursor, text); } else { if (exwrote || mode == MODE_COLON) { redraw(MARK_UNSET, FALSE); } mode = MODE_VI; } } while (mode == MODE_COLON); count = 0L; break; } /* if that command took us out of vi mode, then exit the loop * NOW, without tweaking the cursor or anything. This is very * important when mode == MODE_QUIT. */ if (mode != MODE_VI) { break; } /* now move the cursor, as appropriate */ if (prevkey && ((keyptr->flags & MVMT) #ifndef NO_VISIBLE || V_from #endif ) && count == 0L) { /* movements used as targets are less strict */ tcurs = adjmove(cursor, tcurs, (int)(keyptr->flags | force_flags)); } else if (keyptr->args == CURSOR_MOVED) { /* the < and > keys have FRNT, * but it shouldn't be applied yet */ tcurs = adjmove(cursor, tcurs, FINL); } else { tcurs = adjmove(cursor, tcurs, (int)(keyptr->flags | force_flags | FINL)); } /* was that the end of a d/c/y/</>/! command? */ if (prevkey && ((keyptr->flags & MVMT) #ifndef NO_VISIBLE || V_from #endif ) && count == 0L) { #ifndef NO_VISIBLE /* turn off the hilight */ V_from = 0L; #endif /* if the movement command failed, cancel operation */ if (tcurs == MARK_UNSET) { prevkey = 0; count = 0; continue; } /* make sure range=front and tcurs=rear. Either way, * leave cursor=range since that's where we started. */ cursor = range; if (tcurs < range) { range = tcurs; tcurs = cursor; } /* The 'w' and 'W' destinations should never take us * to the front of a line. Instead, they should take * us only to the end of the preceding line. */ if ((keyptr->flags & NWRP) == NWRP && markline(range) < markline(tcurs) && (markline(tcurs) > nlines || tcurs == m_front(tcurs, 0L))) { tcurs = (tcurs & ~(BLKSIZE - 1)) - BLKSIZE; pfetch(markline(tcurs)); tcurs += plen; } /* adjust for line mode & inclusion of last char/line */ i = (keyptr->flags | vikeys[prevkey].flags); switch ((i | force_flags) & (INCL|LNMD)) { case INCL: tcurs++; break; case INCL|LNMD: tcurs += BLKSIZE; /* fall through... */ case LNMD: range &= ~(BLKSIZE - 1); tcurs &= ~(BLKSIZE - 1); break; } /* run the function */ tcurs = (*vikeys[prevkey].func)(range, tcurs); if (mode == MODE_VI) { (void)adjmove(cursor, cursor, FINL); cursor = adjmove(cursor, tcurs, (int)(vikeys[prevkey].flags | FINL)); } /* cleanup */ prevkey = 0; } else if (!prevkey) { if (tcurs != MARK_UNSET) cursor = tcurs; } } }
/////////////////// // // Distributes a conjunction (AND) over a pair of nodes. // // Post-conditions (memory management): // Every newly created node is either in the return value or was deleted. // Every node (or copy of a node) that is not attached to the return value // is deleted. // Pre- & Post-condition (DNF sub-tree): // Return either an AND with at least two BTERM children, or an OR with // every child being an AND with at least two children. Meaning that // 1 is always represented as (1 /\ 1) in an OR tree. // // SymNode *distr(SymNode *n1, SymNode *n2){ if (n1->t == ETYPE && n2->t == ETYPE) return n1; else if (n1->t == ETYPE) return n2; else if (n2->t == ETYPE) return n1; //Ensure that the first Predicate is always complex unless both are BTERMS if( n1->t == BTERM ){ SymNode *temp = n2; n2 = n1; n1 = temp; } debout("distr is given:n1\n"); deb(n1->printTree(0)); debout("n2\n"); deb(n2->printTree(0)); debout(""); // Because parent of these is an AND, and the code guarantees a "flat" // tree (i.e. no extra AND nodes). assert( (n1->t == SOR || n1->t == BTERM) && (n2->t == SOR || n2->t == BTERM) ); deboutln("di1"); if( n1->t == BTERM ){ //Both are BTerms debout("di1.1"); SymNode *newAnd = new SymNode(SAND, -1); newAnd->addChild(n1); newAnd->addChild(n2); // copied pointers to n1 or n2 // CANNOT destroy them later return newAnd; } deboutln("di2"); // CASE: n1 is OR and n2 is BTERM if(n2->t == BTERM){ debout("di2.1"); for(CLIter cur = n1->children.begin(); cur != n1->children.end(); cur++){ SymNode *copyOfn2 = new SymNode(n2); if( (*cur)->t == BTERM){ (*cur)->addChild(new SymNode(BTERM, (*cur)->bt)); (*cur)->addChild( copyOfn2 ); (*cur)->t = SAND; (*cur)->bt = -1; }else if((*cur)->t == SAND){ (*cur)->addChild(copyOfn2); }else{ assert((*cur)->t != SAND); copyOfn2->destroyNodeShallow(); // BK fixed possible leak } } // Distributed BTERM from n2 across all children of n1 // made the appropriate number of copies of n2 and attached to n1 // Changed node n1 to be type SAND // What happened to n2? SHOULD DESTROY IT. n2->destroyNodeShallow(); // BK fixed leak (8/7/2007) n2 = NULL; // BK fixed leak return n1; // returned an OR rooted subtree with AND children. } deboutln("di3"); assert(n1->t == SOR); assert(n2->t == SOR); // BK 8/21/2009 culling while expanding // requires this case if (n2->children.size() == 0){ n2->destroyNodeShallow(); n2 = NULL; return n1; } // Distribute by making an AND node with children: // 1) a full copy of n1, and 2) a node of n2 // Make the first distribution use the original of n1 // And subsequent copies will use a copy of the original SymNode *newOr = new SymNode(SOR,-1); //Add the first "and" manually SymNode *newAnd = new SymNode(SAND, -1); deboutln(*(n2->children.begin())); newAnd->addChild( *(n2->children.begin()) ) ; // 831 newAnd->addChild(n1); newOr->addChild(newAnd); deboutln("di4"); for(CLIter cur = ++(n2->children.begin()); cur != n2->children.end(); cur++){ //debout("di4.1"); newAnd = new SymNode(SAND, -1); newAnd->addChild((*cur)); newAnd->addChild(n1->copyTree()); // deep copy of n1 newOr->addChild(newAnd); } n2->destroyNodeShallow(); // BK replace above with this (equivalent statement) n2 = NULL; debout("di5"); // n1 is pointed to by newAnd, therefore, it should NOT be destroyed. //MARK changed to newOr for(CLIter cur = newOr->children.begin(); cur != newOr->children.end(); cur++){ (*cur)->distribute(); } newOr->removeParens(); // flatten extra ORs return newOr; // returned a flat OR sub-tree }
/////////////////// // Post-conditions (memory management): // Every node listed in bterms is either affixed to this node or deleted. // // Distributes a conjunction of clauses. // int SymNode::distribute(){ if(t != SAND){ cerr << "distribute called on a non \"and\" node"<<endl; assert(t != SAND); } debout("d1"); //Ensure that there are no ANDs as children removeParens(); debout("d1.1"); CLIter current; ChildList * bterms = new ChildList(); current = children.begin(); // Separate the complex terms from the BTerms; // children will contain only complex terms (i.e. ORs) while( current != children.end() ){ if((*current)->t == BTERM){ bterms->push_back(*current); current = children.erase(current); }else{ current++; } } debout("d2"); // Continue to call distr(Node,Node) until all of my children are // distributed. Recall that children contain ONLY complex nodes. while(children.size() > 1 ){ debout( "d3.1"); SymNode *result = distr( *(children.begin()), *(++children.begin()) ); // BK 8/21/2009 cull to save run-time if (result->t != SAND){ for(CLIter rc = result->children.begin(); rc != result->children.end(); ){ if( (*rc)->cullNode2() ){ rc++; }else{ rc = result->children.erase(rc); } } } // END BK 8/21/2009 children.pop_front(); children.pop_front(); debout("d3.2\nresult tree"); deb(result->printTree(0)); debout("d3.2.1"); //MARK added this assert(result!=0); if(result->t == SAND){ // Result is an AND node, so add its children to the bterms list debout("result->t == SAND)"); bterms->splice(bterms->begin(),result->children); noDuplicateNodes(*bterms); delete result; debout("leave result->t == SAND"); debout("bterms size: "); deboutnn(bterms->size()); }else if( result->t == SOR ){ // Result being an OR, means we added to the children list noDuplicateNodes(result->children); addChild(result); }else if(result->t == BTERM){ bterms->push_back(result); }else if(result->t == FTYPE){ delete result; }else{ cerr << "a returned result was not an \"and\" or an \"or\" or a BTERM" <<endl; assert(0); } } debout("d4"); if( children.size() == 0 && bterms->size() == 1 ){ cerr << "not possible yet.1" <<endl; assert(0); this->t = BTERM; this->bt = (*(bterms->begin()))->bt; delete bterms; // BK fixed unreachable leak return 1; }else if( children.size() == 0 && bterms->size() > 1){ //I stay an AND, but if we culled the ORs then I should be culled as well //That scenario isn't implemented yet children.swap(*bterms); delete bterms; return 1; }else if( children.size() == 0 && bterms->size() == 0){ cerr << "not possible yet." <<endl; assert(0); } // Distribute the leaf bterms into the remaining complex term. debout("d5"); if( children.size() == 1 ){ this->t = SOR; this->bt = -1; SymNode *result = *(children.begin()); children.pop_front(); while (bterms->begin() != bterms->end()){ SymNode* cur = *(bterms->begin()); bterms->pop_front(); result = distr(result, cur); // BK 8/21/2009 cull to save run-time for(CLIter rc = result->children.begin(); rc != result->children.end(); ){ if((*rc)->cullNode2() ){ rc++; }else{ rc = result->children.erase(rc); } } noDuplicateNodes(result->children); // END BK 8/21/2009 debout("distr returned a:"); deb(result->printTree(0)); } // copy the children of the resulting OR into the current children list this->addChildren( result ); delete result; delete bterms; // BK fixed leak (8/7/2007) return 1; }else{ cerr << "there should at least be one child and no bterms or no children and more than 1 bterm" <<endl; assert(0); } // BK: check the size of the bterms array pointer assert (bterms->size() == 0); delete bterms; // BK fixed leak (8/7/2007) return 1; }
/////////////////////// // Post-condition (memory management): // Always return a pointer to this node. // SymNode* SymNode::toDNF(){ debout("toDNF"); CLIter iter,end,dup; if( t == BTERM || t == FTYPE || t == ETYPE || t == TTYPE){ debout("p:isLiteral"); return this; } //Ensure all of the clauses are in DNF iter = children.begin(); end = children.end(); ChildList *newList = new ChildList(); while( iter != end ){ debout("loop:p1"); SymNode *returned; returned = (*iter)->toDNF(); if( returned != NULL ){ newList->push_back(*iter); } iter++; } debout("p2"); this->children.swap( *newList ); newList->clear(); delete newList; deboutnn( "toDNF: children.size(): "); debout(children.size() ); //All chilren are false if they have been pruned by DNF if( children.empty() ){ debout("p:shouldn\'t be happening"); assert(0); this->destroyTree(); return new SymNode(FTYPE,-1); } debout("p3"); if( t == SOR ){ debout("p3.1"); //Then we are fine because all of the clauses are in DNF this->removeParens(); //noDuplicateNodes(this->children); return this; } else if( t == SAND ){ debout("p4"); //We need to distribute "and" over the clauses that are in DNF already //It's exponential time!!!!!!!!! //TEMP MARK // BK: this never happens, because distribute has not line: return 0; if( this->distribute() == 0 ){ assert(0); //Shouldn't be happening debout("p6 this->distribute() == 0"); //The children are false according to our restrictions and so this is false and therefor useless this->destroyTree(); // BK fixed possible leak delete this; return new SymNode(FTYPE,-1); } debout("p5"); //noDuplicateNodes(this->children); return this; }else{ //raise exception "not" is not implemented assert(0); } return NULL; }
void SymTree::cull(){ //FINISH ME //NEEDS TO BE IN DNF BEFORE CALLING debout("c1"); assert(root != 0); if(this->isEmpty() || this->root->t == FTYPE || this->root->t == TTYPE){ ready = 0; return; } if(root->t == SAND){ debout("c2"); if(root->cullNode()){ ready = 1; return; } else{ root = new SymNode(FTYPE,-1); ready = 0; return; } }else if(root->t == SOR){ debout("c3"); CLIter cur = root->children.begin(); while( cur != root->children.end() ){ assert((*cur)->t == BTERM || (*cur)->t == SAND); if( (*cur)->cullNode() ){ cur++; }else{ cur = root->children.erase(cur); } } //All the nodes have been culled or kept and simplified noDuplicateNodes(root->children); if(root->children.size() > 1){ //We have multiple children debout("c4"); ready = 1; rewind(); return; }else if(root->children.size() == 1){ //Only one "and" left, so make it the root debout("c5"); deb(root->printTree(0)); SymNode *soleChild = *(root->children.begin()); root->children.pop_front(); root->addChildren(soleChild); soleChild->children.clear(); root->t = soleChild->t; root->bt = soleChild->bt; soleChild->destroyTree(); ready = 1; return; }else{ //ROOT HAS NO CHILDREN so they've all been falsed debout("c6"); root->destroyTree(); root = new SymNode(FTYPE,-1); ready = 0; return; } }else if(root->t == BTERM){ ready = 1; return; } }
/* readProc - handle messages for the read-file window. This function is used * to handle both help windows and read-message windows. * * arguments: * hWnd handle of window receiving message * command command in message * data data peculiar to the command * * return value: * none * */ VOID PASCAL INTERNAL readProc ( HW hWnd, INT command, WDATA data ) { INT width = TWINWIDTH (hWnd); INT height = TWINHEIGHT (hWnd); INT winSize = width *height *sizeof ( CHAR ); INT oldTop; /* Do NOT initialize this here, hWnd->data may be invalid */ INT i; switch ( command ) { case KEY : oldTop = FT->top; switch ( data ) { case HELP : if ( !fHelp ) { fHelp = TRUE; SpecificHlp ( "reading messages" ); } break; case ESC : fAllowCM = FALSE; CloseWindow ( hWnd ); return; case CTRL_P: case UP : FT->top = max ( 0, FT->top - 1 ); break; case CTRL_N: case DOWN : if ( ( FT->llof == -1 ) || ( FT->top < FT->llof - 1 ) ) FT->top++; break; case CTRL_K: case PGUP : FT->top = max ( 0, FT->top - ( height - 1 ) ); break; case CTRL_L: case PGDN : if ( ( FT->llof == -1 ) || ( FT->top + height - 1 < FT->llof ) ) FT->top += height - 1; break; case CTRL_T: case HOME : FT->top = 0; break; case CTRL_B: case END : if ( FT->llof == -1 ) { FT->top = PAGETOLINE (FT->cPages - 1); while ( GrabNextPage ( hWnd ) ) FT->top += PAGELEN; while ( fSkipToLine ( hWnd, FT->top ) ) FT->top++; FT->top = max ( 0, FT->top - ( height - 2 ) ); } else FT->top = FT->llof - 1; break; default : if ( ( *hWnd->keyProc ) ( hWnd, data ) ) return; break; } /* topLine has moved, so decide how to redraw the read window, */ /* if the window was only moved 1 line, scroll it and draw the */ /* new line, otherwise redraw the whole window. */ if ( ( FT->top == oldTop - 1 ) || ( FT->top == oldTop + 1 ) ) { ScrollWindow ( hWnd, 1, FT->top - oldTop ); if ( FT->top - oldTop < 0 ) { SendMessage ( hWnd, REGENCONT, FT->top + 1 ); SendMessage ( hWnd, PAINT, 0 ); } else { SendMessage ( hWnd, REGENCONT, FT->top + height ); SendMessage ( hWnd, PAINT, height - 1 ); } CheckMore ( hWnd ); } else if ( FT->top != oldTop ) { SendMessage ( hWnd, REGENCONT, NULL ); DrawWindow ( hWnd, FALSE ); } #if DEBUG debout ( "Character %x struck", data ); #endif break; case REGENCONT : /* grab line from file and put it in window's content region */ /* data is a pointer to struct pos. if data == NULL, redo */ /* all lines from FT->top to the end of the window */ if ( data != 0 ) LineToCont ( hWnd, data - 1 ); else { Fill ( ( LPSTR ) hWnd->pContent, ' ', winSize ); for ( i = 0; i <= height - 1; i++) SendMessage ( hWnd, REGENCONT, FT->top + i + 1 ); CheckMore ( hWnd ); } break; case CREATE : hWnd->data = data; FT->pages = ( PLONG ) ZMalloc ( PAGEMAX * sizeof ( *FT->pages ) ); FT->pages [ 0 ] = 0L; FT->cPageMax = PAGEMAX; hWnd->pContent = PoolAlloc ( winSize ); hWnd->contSize = winSize; WindLevel++; SendMessage ( hWnd, REOPNFILE, 0 ); break; case REOPNFILE : FT->fhRead = fopen ( FT->fileRead, "r" ); fseek ( FT->fhRead, 0L, 0 ); FT->cur = FT->top = 0; FT->llof = -1; FT->cPages = 1; SendMessage ( hWnd, REGENCONT, NULL ); /* if data != 0 redraw the window too */ if ( data ) { DrawWindow ( hWnd, FALSE ); CheckMore ( hWnd ); } break; case CLOSEFILE : fclose ( FT->fhRead ); break; case CLOSE : fclose ( FT->fhRead ); if ( FT->fDeleteRead ) _unlink ( FT->fileRead ); ZMfree ( FT->fileRead ); ZMfree ( FT->pages ); ZMfree ( FT ); PoolFree ( hWnd->pContent ); fHelp = FALSE; WindLevel--; if ( hWnd == hReadMessage ) hReadMessage = NULL; break; default : defWndProc (hWnd, command, data); break; } }