static int getCurrentPosition (RoutingData *routing) { ScreenDescription description; describeScreen(&description); if (description.number != routing->screenNumber) { logRouting("screen changed: num=%d", description.number); routing->screenNumber = description.number; return 0; } if (!routing->rowBuffer) { routing->screenRows = description.rows; routing->screenColumns = description.cols; routing->verticalDelta = 0; if (!(routing->rowBuffer = calloc(routing->screenColumns, sizeof(*routing->rowBuffer)))) { logMallocError(); goto error; } logRouting("screen: num=%d cols=%d rows=%d", routing->screenNumber, routing->screenColumns, routing->screenRows); } else if ((routing->screenRows != description.rows) || (routing->screenColumns != description.cols)) { logRouting("size changed: cols=%d rows=%d", description.cols, description.rows); goto error; } routing->cury = description.posy - routing->verticalDelta; routing->curx = description.posx; if (readScreenRow(routing, NULL, description.posy)) return 1; logRouting("read failed: row=%d", description.posy); error: routing->screenNumber = -1; return 0; }
static int awaitCursorMotion (RoutingData *routing, int direction) { int oldx = (routing->oldx = routing->curx); int oldy = (routing->oldy = routing->cury); long timeout = routing->timeSum / routing->timeCount; int moved = 0; TimeValue start; getCurrentTime(&start); while (1) { long time; approximateDelay(ROUTING_INTERVAL); time = millisecondsSince(&start) + 1; { int row = routing->cury + routing->verticalDelta; int bestRow = row; int bestLength = 0; do { ScreenCharacter buffer[routing->screenColumns]; if (!readScreenRow(routing, buffer, row)) break; { int before = routing->curx; int after = before; while (buffer[before].text == routing->rowBuffer[before].text) if (--before < 0) break; while (buffer[after].text == routing->rowBuffer[after].text) if (++after >= routing->screenColumns) break; { int length = after - before - 1; if (length > bestLength) { bestRow = row; if ((bestLength = length) == routing->screenColumns) break; } } } row -= direction; } while ((row >= 0) && (row < routing->screenRows)); routing->verticalDelta = bestRow - routing->cury; } oldy = routing->cury; oldx = routing->curx; if (!getCurrentPosition(routing)) return 0; if ((routing->cury != oldy) || (routing->curx != oldx)) { logRouting("moved: [%d,%d] -> [%d,%d]", oldx, oldy, routing->curx, routing->cury); if (!moved) { moved = 1; timeout = time * 2; routing->timeSum += time * 8; routing->timeCount += 1; } } else if (time > timeout) { if (!moved) { logRouting("timed out"); } break; } } return 1; }
static int awaitCursorMotion (RoutingData *routing, int direction, const CursorAxisEntry *axis) { int moved = 0; long int timeout = routing->timeSum / routing->timeCount; TimeValue start; int trgy = routing->cury; int trgx = routing->curx; routing->oldy = routing->cury; routing->oldx = routing->curx; axis->adjustCoordinate(&trgy, &trgx, direction); getMonotonicTime(&start); while (1) { long int time; TimeValue now; int oldy; int oldx; approximateDelay(ROUTING_INTERVAL); getMonotonicTime(&now); time = millisecondsBetween(&start, &now) + 1; { int row = routing->cury + routing->verticalDelta; int bestRow = row; int bestLength = 0; do { ScreenCharacter buffer[routing->screenColumns]; if (!readScreenRow(routing, buffer, row)) break; { int before = routing->curx; int after = before; while (buffer[before].text == routing->rowBuffer[before].text) if (--before < 0) break; while (buffer[after].text == routing->rowBuffer[after].text) if (++after >= routing->screenColumns) break; { int length = after - before - 1; if (length > bestLength) { bestRow = row; if ((bestLength = length) == routing->screenColumns) break; } } } row -= direction; } while ((row >= 0) && (row < routing->screenRows)); routing->verticalDelta = bestRow - routing->cury; } oldy = routing->cury; oldx = routing->curx; if (!getCurrentPosition(routing)) return 0; if ((routing->cury != oldy) || (routing->curx != oldx)) { logRouting("moved: [%d,%d] -> [%d,%d] (%dms)", oldx, oldy, routing->curx, routing->cury, time); if (!moved) { moved = 1; timeout = (time * 2) + 1; routing->timeSum += time * 8; routing->timeCount += 1; } if ((routing->cury == trgy) && (routing->curx == trgx)) break; if (ROUTING_INTERVAL) { start = now; } else { approximateDelay(1); getMonotonicTime(&start); } } else if (time > timeout) { if (!moved) logRouting("timed out: %ldms", timeout); break; } } return 1; }