static ShowBigText showBigText(S title, fO function, final long delayMS) {
  if (headless()) {
    doEvery(toInt(delayMS), r {
      O data = callF(function);
      print(structureOrText(data));
    });
    null;
  }
  
  final new ShowBigText sbt;
  sbt.title = title;
  sbt.showText("...");
    
  // awt block is important
  installTimer(sbt.is, r {
    // This should work even when the function blocks forever (at least we're not calling it repeatedly in that case)
    
    new Thread("Updater") {
      boolean running;
      public void run() {
        if (!running) {
          running = true;
          S text = null;
          try {
            O data = callF(function);
            if (isString(data))
              text = (S) data;
            else if (data instanceof S[]) {
              S[] x = cast data;
              text = x[0];
              sbt.title = last(x);
            }
          } catch (Throwable e) {
            e.printStackTrace();
            text = exceptionToStringShort(e);
          } finally {
            running = false;
          }
          if (text != null)
            sbt.showText(text);
        }
      }
    }.start();
  }, delayMS, 0);
  ret sbt;
}