// File: /workspace/github_cpp_makefile_star2_O3/tsfn[P]doc2txt/src/doc_format.cpp
// Function: doc_format(Storage const&)
bool doc_format(const Storage &st) {
  const uchar *wds, *ts;
  uint wds_size, ts_size;

  // 取得WordDocument Stream (wds)
  if (!st.stream("WordDocument", &wds, &wds_size)) {
    return false;
  }

  // 取得Table Stream (ts)
  ushort flag1 = *(ushort *)((char *)wds + 0xA);
  bool is1Table = (flag1 & 0x0200) == 0x0200;
  if (!st.stream(is1Table ? "1Table" : "0Table", &ts, &ts_size)) {
    return false;
  }

  uint fcPlcfBtePapx = *(uint *)(wds + 258);
  uint lcbPlcfBtePapx = *(uint *)(wds + 258 + 4);
  uint n = (lcbPlcfBtePapx - 4) / 8;

  set< pair<uint, uint> > ranges;
  for (uint i = 0; i < n; ++i) {
    /* 读取PlcBtePapx中的信息（其实PlcBtePapx在Table Stream中） */
    int fc_start = *(int *)(ts + fcPlcfBtePapx + 4 * i);
    int fc_end = *(int *)(ts + fcPlcfBtePapx + 4 * i + 4);
    uint PnBtePapx = *(uint *)(ts + fcPlcfBtePapx + 4 * (n + 1 + i));

    const uchar *PapxFkp = wds + PnBtePapx * 512;
    uchar cpara = *(const uchar *)(PapxFkp + 511);

    for (uint i = 0; i < cpara; ++i) {
      // rgfc确定文本的位置
      uint rgfc_start = *(uint *)(PapxFkp + 4 * i);
      uint rgfc_end = *(uint *)(PapxFkp + 4 * i + 4);

      // bOffset找到PapxInFkp在PapxFkp中的位置
      uchar bOffset = *(uchar *)(PapxFkp + 4 * (cpara + 1) + 13 * i);

      // 找到PapxInFkp其中的cb, grpprlInPapx
      uchar cb = *(uchar *)(PapxFkp + bOffset * 2);

      // 得到GrpPrlAndIstd
      uint lcbGrpPrlAndIstd = 2 * cb - 1;
      const uchar *GrpPrlAndIstd = PapxFkp + bOffset * 2 + 1;
      if (cb == 0) {
        lcbGrpPrlAndIstd = *GrpPrlAndIstd * 2;
        GrpPrlAndIstd += 1;
      }

      // 根据GrpPrlAndIstd得到段落格式（Direct Paragraph Formatting）
      const uchar *grpprl = GrpPrlAndIstd + 2;
      uint lcb = lcbGrpPrlAndIstd - 1;
      static const int operand_size[8] = { 1, 1, 2, 4, 2, 2, -1, 3, };
      for (uint i = 0; i < lcb;) {
        ushort sprm = *(ushort *)(grpprl + i);
        uint spra = sprm / 8192;
        uint operand;
        i += 2;
        if (spra == 6) {
          i += 1 + *(uchar *)(grpprl + i);
        } else {
          if (operand_size[spra] == 1) {
            operand = *(uchar *)(grpprl + i);
          } else if (operand_size[spra] == 2) {
            operand = *(ushort *)(grpprl + i);
          } else if (operand_size[spra] == 3) {
            operand = *(uint *)(grpprl + i) & 0x00FFFFFF;
          } else if (operand_size[spra] == 4) {
            operand = *(uint *)(grpprl + i);
          } else {
            operand = -1;
          }
          i += operand_size[spra];
        }
        if ((sprm == 0x2403 || sprm == 0x2416) && operand == 1) { // 居中
          ranges.insert(make_pair(rgfc_start, rgfc_end));
        }
      }
    }
  }

  /* 合并各个区间 */
  set< pair<uint, uint> >::iterator iter = ranges.begin(), jter, kter;
  while (iter != ranges.end()) {
    jter = iter;
    ++jter;
    while (jter != ranges.end() && iter->second == jter->first) {
      pair<uint, uint> temp = *iter;
      temp.second = jter->second;
      ranges.erase(iter);
      ranges.insert(temp);
      iter = ranges.find(temp);
      kter = jter;
      ++jter;
      ranges.erase(kter);
    }
    iter = jter;
  }

  /*
  FILE *temp_file = fopen("/dev/shm/middle.txt", "wb");
  for (iter = ranges.begin(); iter != ranges.end(); ++iter) {
    printf("range[%u,%u] is in middle\n", iter->first, iter->second);
    for (uint i = iter->first; i < iter->second && i < wds_size; ++i) {
      fputc(wds[i], temp_file);
    }
  }
  fclose(temp_file);
  */
  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rdi, %rbx
leaq 0x8f6(%rip), %rsi       # 0x3044
leaq -0x38(%rbp), %rdx
leaq -0x90(%rbp), %rcx
callq 0x1a16
testb %al, %al
je 0x2a48
movq -0x38(%rbp), %rax
movzwl 0xa(%rax), %eax
btl $0x9, %eax
leaq 0x8df(%rip), %rax       # 0x3058
leaq 0x8d1(%rip), %rsi       # 0x3051
cmovaeq %rax, %rsi
leaq -0x88(%rbp), %rdx
leaq -0x8c(%rbp), %rcx
movq %rbx, %rdi
callq 0x1a16
testb %al, %al
je 0x2a48
movq -0x38(%rbp), %rax
movl 0x102(%rax), %ecx
movq %rcx, -0x50(%rbp)
movl 0x106(%rax), %edx
addl $-0x4, %edx
leaq -0xb8(%rbp), %rcx
movl $0x0, (%rcx)
xorl %eax, %eax
movq %rax, 0x8(%rcx)
movq %rcx, 0x10(%rcx)
movq %rcx, 0x18(%rcx)
movq %rax, 0x20(%rcx)
cmpl $0x8, %edx
jb 0x2a38
shrl $0x3, %edx
leal 0x1(%rdx), %eax
movq %rax, -0x48(%rbp)
xorl %esi, %esi
movq %rdx, -0x40(%rbp)
movq -0x88(%rbp), %rax
addq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
movq %rsi, -0x58(%rbp)
addq %rsi, %rcx
movl (%rax,%rcx,4), %eax
movq -0x38(%rbp), %rdx
shll $0x9, %eax
movzbl 0x1ff(%rdx,%rax), %ecx
testq %rcx, %rcx
je 0x2973
addq %rax, %rdx
leaq (%rdx,%rcx,4), %rax
addq $0x4, %rax
movq %rax, -0x70(%rbp)
xorl %esi, %esi
movq %rdx, -0x68(%rbp)
movq %rcx, -0x60(%rbp)
leaq (%rsi,%rsi,2), %rax
leaq (%rsi,%rax,4), %rax
movq -0x70(%rbp), %rcx
movzbl (%rcx,%rax), %eax
leaq (%rdx,%rax,2), %rax
movzbl (%rax), %ecx
testl %ecx, %ecx
je 0x2865
leal -0x1(,%rcx,2), %r13d
movl $0x1, %ecx
jmp 0x2872
movzbl 0x1(%rax), %r13d
addl %r13d, %r13d
movl $0x2, %ecx
decl %r13d
movq %rsi, -0x78(%rbp)
je 0x295b
movq (%rdx,%rsi,4), %rdx
movq %rdx, -0x80(%rbp)
leaq (%rax,%rcx), %r14
addq $0x2, %r14
xorl %r12d, %r12d
movl %r12d, %eax
movzwl (%r14,%rax), %ecx
movzwl %cx, %eax
shrl $0xd, %ecx
movl %r12d, %ebx
addl $0x2, %ebx
cmpl $0x6, %ecx
jne 0x28b7
movl %ebx, %ecx
movzbl (%r14,%rcx), %r12d
incl %r12d
jmp 0x291d
cmpl $0x2000, %eax           # imm = 0x2000
setae %dl
cmpw $0x1, %cx
setne %sil
testb %sil, %dl
jne 0x28d5
movl %ebx, %edx
movzbl (%r14,%rdx), %r15d
jmp 0x2912
movl $0x34, %edx
btl %ecx, %edx
jb 0x2903
cmpw $0x3, %cx
je 0x290c
movzwl %cx, %edx
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
cmpl $0x7, %edx
jne 0x2912
movl %ebx, %edx
movl (%r14,%rdx), %r15d
movl $0xffffff, %edx         # imm = 0xFFFFFF
andl %edx, %r15d
jmp 0x2912
movl %ebx, %edx
movzwl (%r14,%rdx), %r15d
jmp 0x2912
movl %ebx, %edx
movl (%r14,%rdx), %r15d
leaq 0x7f7(%rip), %rdx       # 0x3110
movl (%rdx,%rcx,4), %r12d
cmpl $0x2403, %eax           # imm = 0x2403
setne %cl
cmpl $0x2416, %eax           # imm = 0x2416
setne %al
testb %al, %cl
jne 0x294f
cmpl $0x1, %r15d
jne 0x294f
movq -0x80(%rbp), %rax
movq %rax, -0x30(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x2ad6
addl %ebx, %r12d
cmpl %r13d, %r12d
jb 0x2892
movq -0x78(%rbp), %rsi
incq %rsi
movq -0x60(%rbp), %rcx
cmpq %rcx, %rsi
movq -0x68(%rbp), %rdx
jne 0x283b
movq -0x58(%rbp), %rsi
incq %rsi
movq -0x40(%rbp), %rdx
cmpq %rdx, %rsi
jne 0x27f1
movq -0xa8(%rbp), %r15
leaq -0xb8(%rbp), %r13
cmpq %r13, %r15
je 0x2a38
leaq -0xc0(%rbp), %rbx
leaq -0x30(%rbp), %r14
movq %r15, %rdi
callq 0x1120
movq %rax, %r12
cmpq %r13, %rax
je 0x2a1f
movl 0x24(%r15), %eax
cmpl 0x20(%r12), %eax
jne 0x2a1f
movq 0x20(%r15), %rax
movq %rax, -0x30(%rbp)
movl 0x24(%r12), %eax
movl %eax, -0x2c(%rbp)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2c28
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2c6e
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2d3e
movq %rax, %r15
movq %r12, %rdi
callq 0x1120
movq %rax, %r13
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2c28
movq %r13, %r12
leaq -0xb8(%rbp), %rax
cmpq %rax, %r13
jne 0x29b9
jmp 0x2a22
movq %r12, %r13
movq %r13, %r15
leaq -0xb8(%rbp), %rax
cmpq %rax, %r13
movq %rax, %r13
jne 0x29a9
leaq -0xc0(%rbp), %rdi
callq 0x2a78
movb $0x1, %al
jmp 0x2a4a
xorl %eax, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2a60
jmp 0x2a60
movq %rax, %rbx
leaq -0xc0(%rbp), %rdi
callq 0x2a78
movq %rbx, %rdi
callq 0x11a0
nop