Ejemplo n.º 1
0
static void done_string(VTerm *vt, const char *str, size_t len)
{
  if(vt->parser.strbuffer_cur) {
    if(str)
      append_strbuffer(vt, str, len);

    str = vt->parser.strbuffer;
    len = vt->parser.strbuffer_cur;
  }
  else if(!str) {
    DEBUG_LOG("parser.c: TODO: No strbuffer _and_ no final fragment???\n");
    len = 0;
  }

  switch(vt->parser.stringtype) {
  case VTERM_PARSER_OSC:
    if(vt->parser.callbacks && vt->parser.callbacks->osc)
      if((*vt->parser.callbacks->osc)(str, len, vt->parser.cbdata))
        return;

    DEBUG_LOG("libvterm: Unhandled OSC %.*s\n", (int)len, str);
    return;

  case VTERM_PARSER_DCS:
    if(vt->parser.callbacks && vt->parser.callbacks->dcs)
      if((*vt->parser.callbacks->dcs)(str, len, vt->parser.cbdata))
        return;

    DEBUG_LOG("libvterm: Unhandled DCS %.*s\n", (int)len, str);
    return;

  case VTERM_N_PARSER_TYPES:
    return;
  }
}
Ejemplo n.º 2
0
void vterm_push_bytes(VTerm *vt, const char *bytes, size_t len)
{
  size_t pos = 0;
  const char *string_start;

  switch(vt->parser_state) {
  case NORMAL:
    string_start = NULL;
    break;
  case ESC:
  case ESC_IN_OSC:
  case ESC_IN_DCS:
  case CSI:
  case OSC:
  case DCS:
    string_start = bytes;
    break;
  }

#define ENTER_STRING_STATE(st) do { vt->parser_state = st; string_start = bytes + pos + 1; } while(0)
#define ENTER_NORMAL_STATE()   do { vt->parser_state = NORMAL; string_start = NULL; } while(0)

  for( ; pos < len; pos++) {
    unsigned char c = bytes[pos];

    if(c == 0x00 || c == 0x7f) { // NUL, DEL
      if(vt->parser_state != NORMAL) {
        append_strbuffer(vt, string_start, bytes + pos - string_start);
        string_start = bytes + pos + 1;
      }
      continue;
    }
    if(c == 0x18 || c == 0x1a) { // CAN, SUB
      ENTER_NORMAL_STATE();
      continue;
    }
    else if(c == 0x1b) { // ESC
      if(vt->parser_state == OSC)
        vt->parser_state = ESC_IN_OSC;
      else if(vt->parser_state == DCS)
        vt->parser_state = ESC_IN_DCS;
      else
        ENTER_STRING_STATE(ESC);
      continue;
    }
    else if(c == 0x07 &&  // BEL, can stand for ST in OSC or DCS state
            (vt->parser_state == OSC || vt->parser_state == DCS)) {
      // fallthrough
    }
    else if(c < 0x20) { // other C0
      if(vt->parser_state != NORMAL)
        append_strbuffer(vt, string_start, bytes + pos - string_start);
      do_control(vt, c);
      if(vt->parser_state != NORMAL)
        string_start = bytes + pos + 1;
      continue;
    }
    // else fallthrough

    switch(vt->parser_state) {
    case ESC_IN_OSC:
    case ESC_IN_DCS:
      if(c == 0x5c) { // ST
        switch(vt->parser_state) {
          case ESC_IN_OSC: vt->parser_state = OSC; break;
          case ESC_IN_DCS: vt->parser_state = DCS; break;
          default: break;
        }
        do_string(vt, string_start, bytes + pos - string_start - 1);
        ENTER_NORMAL_STATE();
        break;
      }
      vt->parser_state = ESC;
      string_start = bytes + pos;
      // else fallthrough

    case ESC:
      switch(c) {
      case 0x50: // DCS
        ENTER_STRING_STATE(DCS);
        break;
      case 0x5b: // CSI
        ENTER_STRING_STATE(CSI);
        break;
      case 0x5d: // OSC
        ENTER_STRING_STATE(OSC);
        break;
      default:
        if(c >= 0x30 && c < 0x7f) {
          /* +1 to pos because we want to include this command byte as well */
          do_string(vt, string_start, bytes + pos - string_start + 1);
          ENTER_NORMAL_STATE();
        }
        else if(c >= 0x20 && c < 0x30) {
          /* intermediate byte */
        }
        else {
          fprintf(stderr, "TODO: Unhandled byte %02x in Escape\n", c);
        }
      }
      break;

    case CSI:
      if(c >= 0x40 && c <= 0x7f) {
        /* +1 to pos because we want to include this command byte as well */

        do_string(vt, string_start, bytes + pos - string_start + 1);
        ENTER_NORMAL_STATE();
      }
      break;

    case OSC:
    case DCS:
      if(c == 0x07 || (c == 0x9c && !vt->is_utf8)) {
        do_string(vt, string_start, bytes + pos - string_start);
        ENTER_NORMAL_STATE();
      }
      break;

    case NORMAL:
      if(c >= 0x80 && c < 0xa0 && !vt->is_utf8) {
        switch(c) {
        case 0x90: // DCS
          ENTER_STRING_STATE(DCS);
          break;
        case 0x9b: // CSI
          ENTER_STRING_STATE(CSI);
          break;
        case 0x9d: // OSC
          ENTER_STRING_STATE(OSC);
          break;
        default:
          do_control(vt, c);
          break;
        }
      }
      else {
        size_t text_eaten = do_string(vt, bytes + pos, len - pos);

        if(text_eaten == 0) {
          string_start = bytes + pos;
          goto pause;
        }

        pos += (text_eaten - 1); // we'll ++ it again in a moment
      }
      break;
    }
  }

pause:
  if(string_start && string_start < len + bytes) {
    size_t remaining = len - (string_start - bytes);
    append_strbuffer(vt, string_start, remaining);
  }
}
Ejemplo n.º 3
0
static void more_string(VTerm *vt, const char *str, size_t len)
{
  append_strbuffer(vt, str, len);
}
Ejemplo n.º 4
0
static size_t do_string(VTerm *vt, const char *str_frag, size_t len)
{
  if(vt->strbuffer_cur) {
    if(str_frag)
      append_strbuffer(vt, str_frag, len);

    str_frag = vt->strbuffer;
    len = vt->strbuffer_cur;
  }
  else if(!str_frag) {
    fprintf(stderr, "parser.c: TODO: No strbuffer _and_ no final fragment???\n");
    len = 0;
  }

  vt->strbuffer_cur = 0;

  size_t eaten;

  switch(vt->parser_state) {
  case NORMAL:


    if(vt->parser_callbacks && vt->parser_callbacks->text) {
      if((eaten = (*vt->parser_callbacks->text)(str_frag, len, vt->cbdata))) {

        // This is /REALLY/ inconsistant
        if(vt->parser_backup_callbacks && vt->parser_backup_callbacks->text) {
          (*vt->parser_backup_callbacks->text)(str_frag, eaten, vt->cbdata);
        }

        return eaten;
      }
    }


    fprintf(stderr, "libvterm: Unhandled text (%zu chars)\n", len);
    return 0;

  case ESC:
    if(len == 1 && str_frag[0] >= 0x40 && str_frag[0] < 0x60) {
      // C1 emulations using 7bit clean
      // ESC 0x40 == 0x80
      do_control(vt, str_frag[0] + 0x40);
      return 0;
    }
    
    if(vt->parser_backup_callbacks && vt->parser_backup_callbacks->escape)
      (*vt->parser_backup_callbacks->escape)(str_frag, len, vt->cbdata);

    if(vt->parser_callbacks && vt->parser_callbacks->escape)
      if((*vt->parser_callbacks->escape)(str_frag, len, vt->cbdata))
        return 0;

    fprintf(stderr, "libvterm: Unhandled escape ESC 0x%02x\n", str_frag[len-1]);
    return 0;

  case CSI:
    do_string_csi(vt, str_frag, len - 1, str_frag[len - 1]);
    return 0;

  case OSC:
    if(vt->parser_backup_callbacks && vt->parser_backup_callbacks->osc)
      (*vt->parser_backup_callbacks->osc)(str_frag, len, vt->cbdata);

    if(vt->parser_callbacks && vt->parser_callbacks->osc)
      if((*vt->parser_callbacks->osc)(str_frag, len, vt->cbdata))
        return 0;

    fprintf(stderr, "libvterm: Unhandled OSC %.*s\n", (int)len, str_frag);
    return 0;

  case DCS:
    if(vt->parser_callbacks && vt->parser_callbacks->dcs)
      if((*vt->parser_callbacks->dcs)(str_frag, len, vt->cbdata))
        return 0;

    if(vt->parser_backup_callbacks && vt->parser_backup_callbacks->dcs)
      if((*vt->parser_backup_callbacks->dcs)(str_frag, len, vt->cbdata))
				return 0;

    fprintf(stderr, "libvterm: Unhandled DCS %.*s\n", (int)len, str_frag);
    return 0;

  case ESC_IN_OSC:
  case ESC_IN_DCS:
    fprintf(stderr, "libvterm: ARGH! Should never do_string() in ESC_IN_{OSC,DCS}\n");
    return 0;
  }

  return 0;
}