// File: /workspace/github_cpp_makefile_star2_O2/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 0x98a(%rip), %rsi       # 0x3044
leaq -0x38(%rbp), %rdx
leaq -0x88(%rbp), %rcx
callq 0x1998
testb %al, %al
je 0x28c6
movq -0x38(%rbp), %rax
movzwl 0xa(%rax), %eax
btl $0x9, %eax
leaq 0x973(%rip), %rax       # 0x3058
leaq 0x965(%rip), %rsi       # 0x3051
cmovaeq %rax, %rsi
leaq -0x80(%rbp), %rdx
leaq -0x84(%rbp), %rcx
movq %rbx, %rdi
callq 0x1998
testb %al, %al
je 0x28c6
movq -0x38(%rbp), %rax
movl 0x102(%rax), %ecx
movq %rcx, -0x48(%rbp)
movl 0x106(%rax), %ecx
leaq -0xb0(%rbp), %rax
andl $0x0, (%rax)
andq $0x0, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
andq $0x0, 0x20(%rax)
addl $-0x4, %ecx
shrl $0x3, %ecx
movq %rcx, -0x50(%rbp)
leal 0x1(%rcx), %eax
movq %rax, -0x40(%rbp)
xorl %eax, %eax
cmpq -0x50(%rbp), %rax
je 0x28cd
movq %rax, %rdx
movq -0x80(%rbp), %rax
addq -0x48(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rdx, -0x58(%rbp)
addq %rdx, %rcx
movl (%rax,%rcx,4), %eax
movq -0x38(%rbp), %rcx
shll $0x9, %eax
leaq (%rcx,%rax), %rdx
movzbl 0x1ff(%rcx,%rax), %eax
movq %rax, -0x70(%rbp)
leaq (%rdx,%rax,4), %rax
addq $0x4, %rax
movq %rax, -0x68(%rbp)
xorl %esi, %esi
movq %rdx, -0x60(%rbp)
cmpq -0x70(%rbp), %rsi
je 0x28ba
imulq $0xd, %rsi, %rax
movq -0x68(%rbp), %rcx
movzbl (%rcx,%rax), %eax
leaq (%rdx,%rax,2), %rax
movzbl (%rax), %ecx
testl %ecx, %ecx
je 0x27c7
leal -0x1(,%rcx,2), %r13d
pushq $0x1
jmp 0x27d1
movzbl 0x1(%rax), %r13d
addl %r13d, %r13d
pushq $0x2
popq %rcx
movq %rsi, -0x78(%rbp)
movq (%rdx,%rsi,4), %r15
leaq (%rax,%rcx), %rbx
addq $0x2, %rbx
decl %r13d
xorl %r14d, %r14d
cmpl %r13d, %r14d
jae 0x28aa
movl %r14d, %eax
movzwl (%rbx,%rax), %eax
movl %eax, %edx
shrl $0xd, %edx
movl %r14d, %ecx
addl $0x2, %ecx
movl %ecx, %esi
cmpl $0x6, %edx
jne 0x2814
movzbl (%rbx,%rsi), %r14d
incl %r14d
jmp 0x286e
cmpw $0x2000, %ax            # imm = 0x2000
setae %dil
cmpw $0x1, %dx
setne %r8b
testb %r8b, %dil
jne 0x2830
movzbl (%rbx,%rsi), %r12d
jmp 0x2863
pushq $0x34
popq %rdi
btl %edx, %edi
jb 0x2858
cmpw $0x3, %dx
je 0x285f
movzwl %dx, %edi
pushq $-0x1
popq %r12
cmpl $0x7, %edi
jne 0x2863
movl (%rbx,%rsi), %r12d
movl $0xffffff, %esi         # imm = 0xFFFFFF
andl %esi, %r12d
jmp 0x2863
movzwl (%rbx,%rsi), %r12d
jmp 0x2863
movl (%rbx,%rsi), %r12d
leaq 0x8a6(%rip), %rsi       # 0x3110
movl (%rsi,%rdx,4), %r14d
addl %ecx, %r14d
cmpw $0x2403, %ax            # imm = 0x2403
setne %cl
cmpw $0x2416, %ax            # imm = 0x2416
setne %al
testb %al, %cl
jne 0x27e8
cmpl $0x1, %r12d
jne 0x27e8
movq %r15, -0x30(%rbp)
leaq -0xb8(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x29f8
jmp 0x27e8
movq -0x78(%rbp), %rsi
incq %rsi
movq -0x60(%rbp), %rdx
jmp 0x279a
movq -0x58(%rbp), %rax
incq %rax
jmp 0x274e
xorl %eax, %eax
jmp 0x296f
leaq -0xb8(%rbp), %rbx
movq 0x18(%rbx), %r15
leaq -0x30(%rbp), %r14
leaq -0xb0(%rbp), %rax
cmpq %rax, %r15
je 0x2961
movq %r15, %rdi
callq 0x1140
movq %rax, %r12
leaq -0xb0(%rbp), %rax
cmpq %rax, %r12
je 0x2959
movl 0x24(%r15), %eax
cmpl 0x20(%r12), %eax
jne 0x2959
movq 0x20(%r15), %rax
movq %rax, -0x30(%rbp)
movl 0x24(%r12), %eax
movl %eax, -0x2c(%rbp)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2bda
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2c3c
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2d20
movq %rax, %r15
movq %r12, %rdi
callq 0x1140
movq %rax, %r13
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2bda
movq %r13, %r12
jmp 0x28f3
movq %r12, %r15
jmp 0x28dc
leaq -0xb8(%rbp), %rdi
callq 0x299c
movb $0x1, %al
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2985
jmp 0x2985
movq %rax, %rbx
leaq -0xb8(%rbp), %rdi
callq 0x299c
movq %rbx, %rdi
callq 0x11c0