2024
0207
w3m

mainloop

いよいよ本格的な改造に踏み込みはじめる。 mainloop を分離した。

unknown: html => {"type":"html","value":"<!-- truncate -->","position":{"start":{"line":5,"column":1,"offset":39},"end":{"line":5,"column":18,"offset":56}}}

100行ちょいしかなかったの貼ってみる。

mainloop

void mainLoop() {
  for (;;) {
    if (popAddDownloadList()) {
      ldDL();
    }
    if (Currentbuf->submit) {
      Anchor *a = Currentbuf->submit;
      Currentbuf->submit = NULL;
      gotoLine(Currentbuf, a->start.line);
      Currentbuf->pos = a->start.pos;
      _followForm(true);
      continue;
    }

    // event processing
    if (CurrentEvent) {
      CurrentKey = -1;
      CurrentKeyData = NULL;
      CurrentCmdData = (char *)CurrentEvent->data;
      w3mFuncList[CurrentEvent->cmd].func();
      CurrentCmdData = NULL;
      CurrentEvent = CurrentEvent->next; // イベント。リンクリストになっている。デキューしている
      continue;
    }

    // get keypress event
    if (Currentbuf->event) {
      if (Currentbuf->event->status != AL_UNSET) {
        CurrentAlarm = Currentbuf->event;
        if (CurrentAlarm->sec == 0) { /* refresh (0sec) */
          Currentbuf->event = NULL;
          CurrentKey = -1;
          CurrentKeyData = NULL;
          CurrentCmdData = (char *)CurrentAlarm->data;
          w3mFuncList[CurrentAlarm->cmd].func();
          CurrentCmdData = NULL;
          continue;
        }
      } else
        Currentbuf->event = NULL;
    }
    if (!Currentbuf->event)
      CurrentAlarm = &DefaultAlarm;
    if (CurrentAlarm->sec > 0) {
      mySignal(SIGALRM, SigAlarm);
      alarm(CurrentAlarm->sec);
    }
    mySignal(SIGWINCH, resize_hook);
    {
      do {
        if (need_resize_screen)
          resize_screen();
      } while (sleep_till_anykey(1, 0) <= 0);
    }
    auto c = getch(); // 👈 ブロック
    if (CurrentAlarm->sec > 0) {
      alarm(0);
    }
    if (IS_ASCII(c)) { /* Ascii */
      if (('0' <= c) && (c <= '9') &&
          (prec_num || (GlobalKeymap[c] == FUNCNAME_nulcmd))) {
        prec_num = prec_num * 10 + (int)(c - '0');
        if (prec_num > PREC_LIMIT)
          prec_num = PREC_LIMIT;
      } else {
        set_buffer_environ(Currentbuf);
        save_buffer_position(Currentbuf);
        keyPressEventProc((int)c); // 👈 KeyMap で dispatch
        prec_num = 0;
      }
    }
    prev_key = CurrentKey;
    CurrentKey = -1;
    CurrentKeyData = NULL;
  }
}

mainloop は無限loop で実装されていて getch 関数でキーボード入力をブロックしています。 あとはシグナルのわりこみイベントがあります。 主要な入力は以下です。

  • keyboard

  • signal: SIGWINCH term の resize

  • signal: SIGALRM timer イベント

  • signal: SIGINT ctrl-c

キーボードが入力すると KeyMap のコールバックを実行して、 ループが一回まわります。 このとき、イベントが来ていれば処理されます。 なので、git アニメのコマを送るのにキーボード連打が必要だったりします。

libuv にうってつけ

ループを libuv 管理にして、 キーボードやシグナルなどの入力を一元的に管理することを目論んでいる。 以下も追加できる予定。

  • Windows 互換(POSIXがだいたい隠蔽できる)

  • network 処理 の非同期化(ダウンロード中のタブ切り替えなど)

  • アニメーション実行(あとで)