Exemple #1
0
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;
}
Exemple #2
0
static void
moveCursor (RoutingData *routing, const CursorDirectionEntry *direction) {
#ifdef SIGUSR1
  sigset_t oldMask;
  sigprocmask(SIG_BLOCK, &routing->signalMask, &oldMask);
#endif /* SIGUSR1 */

  logRouting("move: %s", direction->name);
  insertScreenKey(direction->key);

#ifdef SIGUSR1
  sigprocmask(SIG_SETMASK, &oldMask, NULL);
#endif /* SIGUSR1 */
}
Exemple #3
0
static RoutingStatus
doRouting (int column, int row, int screen) {
  RoutingData routing;

#ifdef SIGUSR1
  /* Set up the signal mask. */
  sigemptyset(&routing.signalMask);
  sigaddset(&routing.signalMask, SIGUSR1);
  sigprocmask(SIG_UNBLOCK, &routing.signalMask, NULL);
#endif /* SIGUSR1 */

  /* initialize the routing data structure */
  routing.screenNumber = screen;
  routing.rowBuffer = NULL;
  routing.timeSum = ROUTING_TIMEOUT;
  routing.timeCount = 1;

  if (getCurrentPosition(&routing)) {
    logRouting("from: [%d,%d]", routing.curx, routing.cury);

    if (column < 0) {
      adjustCursorVertically(&routing, 0, row);
    } else {
      if (adjustCursorVertically(&routing, -1, row) != CRR_FAIL)
        if (adjustCursorHorizontally(&routing, 0, row, column) == CRR_NEAR)
          if (routing.cury < row)
            if (adjustCursorVertically(&routing, 1, routing.cury+1) != CRR_FAIL)
              adjustCursorHorizontally(&routing, 0, row, column);
    }
  }

  if (routing.rowBuffer) free(routing.rowBuffer);

  if (routing.screenNumber != screen) return ROUTING_ERROR;
  if (routing.cury != row) return ROUTING_WRONG_ROW;
  if ((column >= 0) && (routing.curx != column)) return ROUTING_WRONG_COLUMN;
  return ROUTING_DONE;
}
Exemple #4
0
static RoutingResult
adjustCursorPosition (RoutingData *routing, int where, int trgy, int trgx, const CursorAxisEntry *axis) {
  logRouting("to: [%d,%d]", trgx, trgy);

  while (1) {
    int dify = trgy - routing->cury;
    int difx = (trgx < 0)? 0: (trgx - routing->curx);
    int dir;

    /* determine which direction the cursor needs to move in */
    if (dify) {
      dir = (dify > 0)? 1: -1;
    } else if (difx) {
      dir = (difx > 0)? 1: -1;
    } else {
      return CRR_DONE;
    }

    /* tell the cursor to move in the needed direction */
    moveCursor(routing, ((dir > 0)? axis->forward: axis->backward));
    if (!awaitCursorMotion(routing, dir)) return CRR_FAIL;

    if (routing->cury != routing->oldy) {
      if (routing->oldy != trgy) {
        if (((routing->cury - routing->oldy) * dir) > 0) {
          int dif = trgy - routing->cury;
          if ((dif * dify) >= 0) continue;
          if (where > 0) {
            if (routing->cury > trgy) return CRR_NEAR;
          } else if (where < 0) {
            if (routing->cury < trgy) return CRR_NEAR;
          } else {
            if ((dif * dif) < (dify * dify)) return CRR_NEAR;
          }
        }
      }
    } else if (routing->curx != routing->oldx) {
      if (((routing->curx - routing->oldx) * dir) > 0) {
        int dif = trgx - routing->curx;
        if (routing->cury != trgy) continue;
        if ((dif * difx) >= 0) continue;
        if (where > 0) {
          if (routing->curx > trgx) return CRR_NEAR;
        } else if (where < 0) {
          if (routing->curx < trgx) return CRR_NEAR;
        } else {
          if ((dif * dif) < (difx * difx)) return CRR_NEAR;
        }
      }
    } else {
      return CRR_NEAR;
    }

    /* We're getting farther from our target. Before giving up, let's
     * try going back to the previous position since it was obviously
     * the nearest ever reached.
     */
    moveCursor(routing, ((dir > 0)? axis->backward: axis->forward));
    return awaitCursorMotion(routing, -dir)? CRR_NEAR: CRR_FAIL;
  }
}
Exemple #5
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;
}
Exemple #6
0
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;
}