ResultType WinGroup::Deactivate(bool aStartWithMostRecent) { if (IsEmpty()) return OK; // OK since this is the expected behavior in this case. // Otherwise: if (!Update(false)) // Update our private member vars. return FAIL; // It already displayed the error for us. HWND active_window = GetForegroundWindow(); if (IsMember(active_window, *g)) sAlreadyVisitedCount = 0; // Activate the next unvisited non-member: WindowSearch ws; ws.mFindLastMatch = !aStartWithMostRecent || sAlreadyVisitedCount; ws.mAlreadyVisited = sAlreadyVisited; ws.mAlreadyVisitedCount = sAlreadyVisitedCount; ws.mFirstWinSpec = mFirstWindow; EnumWindows(EnumParentFindAnyExcept, (LPARAM)&ws); if (ws.mFoundParent) { // If the window we're about to activate owns other visble parent windows, it can // never truly be activated because it must always be below them in the z-order. // Thus, instead of activating it, activate the first (and usually the only?) // visible window that it owns. Doing this makes things nicer for some apps that // have a pair of main windows, such as MS Visual Studio (and probably many more), // because it avoids activating such apps twice in a row as the user progresses // through the sequence: HWND first_visible_owned = WindowOwnsOthers(ws.mFoundParent); if (first_visible_owned) { MarkAsVisited(ws.mFoundParent); // Must mark owner as well as the owned window. // Activate the owned window instead of the owner because it usually // (probably always, given the comments above) is the real main window: ws.mFoundParent = first_visible_owned; } SetForegroundWindowEx(ws.mFoundParent); // Probably best to do this before WinDelay in case another hotkey fires during the delay: MarkAsVisited(ws.mFoundParent); DoWinDelay; } else // No window was found to activate (they have all been visited). { if (sAlreadyVisitedCount) { bool wrap_around = (sAlreadyVisitedCount > 1); sAlreadyVisitedCount = 0; if (wrap_around) { // The user pressed a hotkey to do something, yet nothing has happened yet. // We want something to happen every time if there's a qualifying // "something" that we can do. And in this case there is: we can start // over again through the list, excluding the foreground window (which // the user has already had a chance to review): MarkAsVisited(active_window); // Make a recursive call to self. This can't result in an infinite // recursion (stack fault) because the called layer will only // recurse a second time if sAlreadyVisitedCount > 1, which is // impossible with the current logic: Deactivate(false); // Seems best to ignore aStartWithMostRecent in this case? } } } // Even if a window wasn't found, we've done our job so return OK: return OK; }
VALUE DetermineZeroValue(POSITION position) { POSITION i,lowSeen,highSeen; POSITION numUndecided, oldNumUndecided, numNew; MOVELIST *moveptr, *headMove; POSITION child; VALUE childValue; POSITION numTot, numWin, numTie; int tieRemoteness, winRemoteness; //if (gTwoBits) // InitializeVisitedArray(); StoreValueOfPosition(position,Primitive(position)); MarkAsVisited(position); oldNumUndecided = 0; numUndecided = 1; numNew = 1; lowSeen = position; highSeen = lowSeen+1; while((numUndecided != oldNumUndecided) || (numNew != 0)) { oldNumUndecided = numUndecided; numUndecided = 0; numNew = 0; for(i = lowSeen; i <= highSeen; i++) { if(Visited(i)) { if(GetValueOfPosition(i) == undecided) { moveptr = headMove = GenerateMoves(i); numTot = numWin = numTie = 0; tieRemoteness = winRemoteness = REMOTENESS_MAX; while(moveptr != NULL) { child = DoMove(i,moveptr->move); numTot++; if(Visited(child)) childValue = GetValueOfPosition(child); else{ childValue = Primitive(child); numNew++; MarkAsVisited(child); StoreValueOfPosition(child,childValue); if(childValue != undecided) { SetRemoteness(child,0); } if(child < lowSeen) lowSeen = child; if(child > highSeen) highSeen = child + 1; } if(childValue == lose) { StoreValueOfPosition(i,win); if(Remoteness(i) > Remoteness(child)+1) SetRemoteness(i,Remoteness(child)+1); } if(childValue == win) { numWin++; if(Remoteness(child) < winRemoteness) { winRemoteness = Remoteness(child); } } if(childValue == tie) { numTie++; if(Remoteness(child) < tieRemoteness) { tieRemoteness = Remoteness(child); } } moveptr = moveptr->next; } FreeMoveList(headMove); if((numTot != 0) && (numTot == numWin + numTie)) { if(numTie == 0) { SetRemoteness(i, winRemoteness+1); StoreValueOfPosition(i,lose); }else{ SetRemoteness(i, tieRemoteness+1); StoreValueOfPosition(i,tie); } } if(GetValueOfPosition(i) == undecided) numUndecided++; } } } printf("\nnumUndecided: " POSITION_FORMAT ", diff: " POSITION_FORMAT ", numNew: " POSITION_FORMAT ", lowSeen: " POSITION_FORMAT ", highSeen: " POSITION_FORMAT, numUndecided,numUndecided - oldNumUndecided,numNew,lowSeen,highSeen); } for(i = 0; i < gNumberOfPositions; i++) { if(Visited(i) && (GetValueOfPosition(i) == undecided)) { SetRemoteness(i,REMOTENESS_MAX); StoreValueOfPosition(i, tie); } UnMarkAsVisited(i); } return GetValueOfPosition(position); }
ResultType WinGroup::Activate(bool aStartWithMostRecent, WindowSpec *aWinSpec, Label **aJumpToLabel) { if (aJumpToLabel) // Initialize early in case of early return. *aJumpToLabel = NULL; if (IsEmpty()) return OK; // OK since this is the expected behavior in this case. // Otherwise: if (!Update(true)) // Update our private member vars. return FAIL; // It already displayed the error for us. WindowSpec *win, *win_to_activate_next = aWinSpec; bool group_is_active = false; // Set default. HWND activate_win, active_window = GetForegroundWindow(); // This value is used in more than one place. if (win_to_activate_next) { // The caller told us which WindowSpec to start off trying to activate. // If the foreground window matches that WindowSpec, do nothing except // marking it as visited, because we want to stay on this window under // the assumption that it was newly revealed due to a window on top // of it having just been closed: if (win_to_activate_next == IsMember(active_window, *g)) { group_is_active = true; MarkAsVisited(active_window); return OK; } // else don't mark as visited even if it's a member of the group because // we're about to attempt to activate a different window: the next // unvisited member of this same WindowSpec. If the below doesn't // find any of those, it continue on through the list normally. } else // Caller didn't tell us which, so determine it. { if (win_to_activate_next = IsMember(active_window, *g)) // Foreground window is a member of this group. { // Set it to activate this same WindowSpec again in case there's // more than one that matches (e.g. multiple notepads). But first, // mark the current window as having been visited if it hasn't // already by marked by a prior iteration. Update: This method // doesn't work because if a unvisted matching window became the // foreground window by means other than using GroupActivate // (e.g. launching a new instance of the app: now there's another // matching window in the foreground). So just call it straight // out. It has built-in dupe-checking which should prevent the // list from filling up with dupes if there are any special // situations in which that might otherwise happen: //if (!sAlreadyVisitedCount) group_is_active = true; MarkAsVisited(active_window); } else // It's not a member. { win_to_activate_next = mFirstWindow; // We're starting fresh, so start at the first window. // Reset the list of visited windows: sAlreadyVisitedCount = 0; } } // Activate any unvisited window that matches the win_to_activate_next spec. // If none, activate the next window spec in the series that does have an // existing window: // If the spec we're starting at already has some windows marked as visited, // set this variable so that we know to retry the first spec again in case // a full circuit is made through the window specs without finding a window // to activate. Note: Using >1 vs. >0 might protect against any infinite-loop // conditions that may be lurking: bool retry_starting_win_spec = (sAlreadyVisitedCount > 1); bool retry_is_in_effect = false; for (win = win_to_activate_next;;) { // Call this in the mode to find the last match, which makes things nicer // because when the sequence wraps around to the beginning, the windows will // occur in the same order that they did the first time, rather than going // backwards through the sequence (which is counterintuitive for the user): if ( activate_win = WinActivate(*g, win->mTitle, win->mText, win->mExcludeTitle, win->mExcludeText // This next line is whether to find last or first match. We always find the oldest // (bottommost) match except when the user has specifically asked to start with the // most recent. But it only makes sense to start with the most recent if the // group isn't currently active (i.e. we're starting fresh), because otherwise // windows would be activated in an order different from what was already shown // the first time through the enumeration, which doesn't seem to be ever desirable: , !aStartWithMostRecent || group_is_active , sAlreadyVisited, sAlreadyVisitedCount) ) { // We found a window to activate, so we're done. // Probably best to do this before WinDelay in case another hotkey fires during the delay: MarkAsVisited(activate_win); DoWinDelay; //MsgBox(win->mText, 0, win->mTitle); break; } // Otherwise, no window was found to activate. if (retry_is_in_effect) // This was the final attempt because we've already gone all the // way around the circular linked list of WindowSpecs. This check // must be done, otherwise an infinite loop might result if the windows // that formed the basis for determining the value of // retry_starting_win_spec have since been destroyed: break; // Otherwise, go onto the next one in the group: win = win->mNextWindow; // Even if the above didn't change the value of <win> (because there's only // one WinSpec in the list), it's still correct to reset this count because // we want to start the fresh again after all the windows have been // visited. Note: The only purpose of sAlreadyVisitedCount as used by // this function is to indicate which windows in a given WindowSpec have // been visited, not which windows altogether (i.e. it's not necessary to // remember which windows have been visited once we move on to a new // WindowSpec). sAlreadyVisitedCount = 0; if (win == win_to_activate_next) { // We've made one full circuit of the circular linked list without // finding an existing window to activate. At this point, the user // has pressed a hotkey to do a GroupActivate, but nothing has happened // yet. We always want something to happen unless there's absolutely // no existing windows to activate, or there's only a single window in // the system that matches the group and it's already active. if (retry_starting_win_spec) { // Mark the foreground window as visited so that it won't be // mistakenly activated again by the next iteration: MarkAsVisited(active_window); retry_is_in_effect = true; // Now continue with the next iteration of the loop so that it // will activate a different instance of this WindowSpec rather // than getting stuck on this one. } else { if (aJumpToLabel && mJumpToLabel) { // Caller asked us to return in this case, so that it can // use this value to execute a user-specified Gosub: *aJumpToLabel = mJumpToLabel; // Set output param for the caller. } return FAIL; // Let GroupActivate set ErrorLevel to indicate what happened. } } } return OK; }
void WriteNode(FILE *fp, POSITION node, int level, EDGELIST *tree) { OPEN_POS_DATA pdata; REMOTENESS nodeRemoteness; char label[50]; if(kLoopy && gUseOpen) { pdata = GetOpenData(node); } else { pdata = 0; } if(!Visited(node)) { if(level != GetLevelNumber(pdata)) { fprintf(fp, "\t\tsubgraph cluster%llu {\n", node); fprintf(fp, "\t\t\tlabel = \" \"\n"); fprintf(fp, "\t\t\tcolor = \"blue\"\n\t"); sprintf(label, "\\nlvl %d", GetLevelNumber(pdata)); } else { sprintf(label, " "); } if(node == gInitialPosition) { if(level == GetLevelNumber(pdata)) { fprintf(fp, "\t\tsubgraph cluster%llu {\n", node); fprintf(fp, "\t\t\tcolor = \"blue\"\n\t"); } fprintf(fp, "%slabel = \"Initial Position\"\n\t", (level == GetLevelNumber(pdata)) ? "\t\t\t" : "\t\t"); } if(GetLevelNumber(pdata) == 0) { MarkAsVisited(node); fprintf(fp, "\t\t%llu [color = \"%s\", style = \"filled\", shape = \"%s\", label = \"%llu%s\"]", node, PositionColor(node), PositionShape(node), node, label); } else if(GetLevelNumber(pdata) > 0) { MarkAsVisited(node); fprintf(fp, "\t\t%llu [color = \"%s\", style = \"filled\", peripheries = %d, shape = \"%s\", label = \"%llu%s\"]", node, PositionColor(node), GetCorruptionLevel(pdata) + 1, PositionShape(node), node, label); } else { BadElse("WriteNode"); } if(level != GetLevelNumber(pdata) || node == gInitialPosition) { fprintf(fp, "\n\t\t}\n"); } else { fprintf(fp, "\n"); } /* Determine rank of node */ if(GetLevelNumber(pdata) == 0) { nodeRemoteness = Remoteness(node); } else { nodeRemoteness = GetFremoteness(pdata); } //0-REMOTENESS_MAX-1 regular nodes, //REMOTENESS_MAX level above current level, //REMOTENESS_MAX+1 level below current level if(gRemotenessOrder) { if(level == GetLevelNumber(pdata)) { if(GetFringe(pdata)) { UpdateRankList(tree, node, REMOTENESS_MAX+1); // want fringes at bottom } else { UpdateRankList(tree, node, nodeRemoteness); } } else if(level > GetLevelNumber(pdata)) { UpdateRankList(tree, node, REMOTENESS_MAX+1); } else if(level < GetLevelNumber(pdata)) { UpdateRankList(tree, node, REMOTENESS_MAX); } else { BadElse("WriteNode"); } } } }