// File: 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
subq $0x1a0, %rsp            # imm = 0x1A0
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
leaq 0x1e3b(%rip), %rsi      # 0x6045
leaq -0x18(%rbp), %rdx
leaq -0x24(%rbp), %rcx
callq 0x1e80
testb $0x1, %al
jne 0x4224
movb $0x0, -0x1(%rbp)
jmp 0x48dd
movq -0x18(%rbp), %rax
movw 0xa(%rax), %ax
movw %ax, -0x2a(%rbp)
movzwl -0x2a(%rbp), %eax
andl $0x200, %eax            # imm = 0x200
cmpl $0x200, %eax            # imm = 0x200
sete %al
andb $0x1, %al
movb %al, -0x2b(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x158(%rbp)
testb $0x1, -0x2b(%rbp)
je 0x4267
leaq 0x1df4(%rip), %rax      # 0x6052
movq %rax, -0x160(%rbp)
jmp 0x4277
leaq 0x1deb(%rip), %rax      # 0x6059
movq %rax, -0x160(%rbp)
jmp 0x4277
movq -0x158(%rbp), %rdi
movq -0x160(%rbp), %rsi
leaq -0x20(%rbp), %rdx
leaq -0x28(%rbp), %rcx
callq 0x1e80
testb $0x1, %al
jne 0x429f
movb $0x0, -0x1(%rbp)
jmp 0x48dd
movq -0x18(%rbp), %rax
movl 0x102(%rax), %eax
movl %eax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movl 0x106(%rax), %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
subl $0x4, %eax
shrl $0x3, %eax
movl %eax, -0x38(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x4900
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x38(%rbp), %eax
jae 0x46b5
movq -0x20(%rbp), %rax
movl -0x30(%rbp), %ecx
addq %rcx, %rax
movl -0x6c(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl (%rax,%rcx), %eax
movl %eax, -0x70(%rbp)
movq -0x20(%rbp), %rax
movl -0x30(%rbp), %ecx
addq %rcx, %rax
movl -0x6c(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl 0x4(%rax,%rcx), %eax
movl %eax, -0x74(%rbp)
movq -0x20(%rbp), %rax
movl -0x30(%rbp), %ecx
addq %rcx, %rax
movl -0x38(%rbp), %ecx
addl $0x1, %ecx
addl -0x6c(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl (%rax,%rcx), %eax
movl %eax, -0x78(%rbp)
movq -0x18(%rbp), %rax
movl -0x78(%rbp), %ecx
shll $0x9, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movb 0x1ff(%rax), %al
movb %al, -0x81(%rbp)
movl $0x0, -0x88(%rbp)
movl -0x88(%rbp), %eax
movzbl -0x81(%rbp), %ecx
cmpl %ecx, %eax
jae 0x46a5
movq -0x80(%rbp), %rax
movl -0x88(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl (%rax,%rcx), %eax
movl %eax, -0x8c(%rbp)
movq -0x80(%rbp), %rax
movl -0x88(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl 0x4(%rax,%rcx), %eax
movl %eax, -0x90(%rbp)
movq -0x80(%rbp), %rax
movzbl -0x81(%rbp), %ecx
addl $0x1, %ecx
shll $0x2, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
imull $0xd, -0x88(%rbp), %ecx
movl %ecx, %ecx
movb (%rax,%rcx), %al
movb %al, -0x91(%rbp)
movq -0x80(%rbp), %rax
movzbl -0x91(%rbp), %ecx
shll %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %al
movb %al, -0x92(%rbp)
movzbl -0x92(%rbp), %eax
shll %eax
subl $0x1, %eax
movl %eax, -0x98(%rbp)
movq -0x80(%rbp), %rax
movzbl -0x91(%rbp), %ecx
shll %ecx
movslq %ecx, %rcx
addq %rcx, %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
movzbl -0x92(%rbp), %eax
cmpl $0x0, %eax
jne 0x4445
movq -0xa0(%rbp), %rax
movzbl (%rax), %eax
shll %eax
movl %eax, -0x98(%rbp)
movq -0xa0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
addq $0x2, %rax
movq %rax, -0xa8(%rbp)
movl -0x98(%rbp), %eax
subl $0x1, %eax
movl %eax, -0xac(%rbp)
movl $0x0, -0xb0(%rbp)
movl -0xb0(%rbp), %eax
cmpl -0xac(%rbp), %eax
jae 0x468f
movq -0xa8(%rbp), %rax
movl -0xb0(%rbp), %ecx
movw (%rax,%rcx), %ax
movw %ax, -0xb2(%rbp)
movzwl -0xb2(%rbp), %eax
movl $0x2000, %ecx           # imm = 0x2000
cltd
idivl %ecx
movl %eax, -0xb8(%rbp)
movl -0xb0(%rbp), %eax
addl $0x2, %eax
movl %eax, -0xb0(%rbp)
cmpl $0x6, -0xb8(%rbp)
jne 0x44ec
movq -0xa8(%rbp), %rax
movl -0xb0(%rbp), %ecx
movzbl (%rax,%rcx), %eax
addl $0x1, %eax
addl -0xb0(%rbp), %eax
movl %eax, -0xb0(%rbp)
jmp 0x45d8
movl -0xb8(%rbp), %eax
movl %eax, %ecx
leaq 0x1be5(%rip), %rax      # 0x60e0
cmpl $0x1, (%rax,%rcx,4)
jne 0x451d
movq -0xa8(%rbp), %rax
movl -0xb0(%rbp), %ecx
movzbl (%rax,%rcx), %eax
movl %eax, -0xbc(%rbp)
jmp 0x45ba
movl -0xb8(%rbp), %eax
movl %eax, %ecx
leaq 0x1bb4(%rip), %rax      # 0x60e0
cmpl $0x2, (%rax,%rcx,4)
jne 0x454b
movq -0xa8(%rbp), %rax
movl -0xb0(%rbp), %ecx
movzwl (%rax,%rcx), %eax
movl %eax, -0xbc(%rbp)
jmp 0x45b8
movl -0xb8(%rbp), %eax
movl %eax, %ecx
leaq 0x1b86(%rip), %rax      # 0x60e0
cmpl $0x3, (%rax,%rcx,4)
jne 0x457d
movq -0xa8(%rbp), %rax
movl -0xb0(%rbp), %ecx
movl (%rax,%rcx), %eax
andl $0xffffff, %eax         # imm = 0xFFFFFF
movl %eax, -0xbc(%rbp)
jmp 0x45b6
movl -0xb8(%rbp), %eax
movl %eax, %ecx
leaq 0x1b54(%rip), %rax      # 0x60e0
cmpl $0x4, (%rax,%rcx,4)
jne 0x45aa
movq -0xa8(%rbp), %rax
movl -0xb0(%rbp), %ecx
movl (%rax,%rcx), %eax
movl %eax, -0xbc(%rbp)
jmp 0x45b4
movl $0xffffffff, -0xbc(%rbp) # imm = 0xFFFFFFFF
jmp 0x45b6
jmp 0x45b8
jmp 0x45ba
movl -0xb8(%rbp), %eax
movl %eax, %ecx
leaq 0x1b17(%rip), %rax      # 0x60e0
movl (%rax,%rcx,4), %eax
addl -0xb0(%rbp), %eax
movl %eax, -0xb0(%rbp)
movzwl -0xb2(%rbp), %eax
cmpl $0x2403, %eax           # imm = 0x2403
je 0x45f8
movzwl -0xb2(%rbp), %eax
cmpl $0x2416, %eax           # imm = 0x2416
jne 0x468a
cmpl $0x1, -0xbc(%rbp)
jne 0x468a
leaq -0x8c(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x4970
movq %rax, -0x168(%rbp)
jmp 0x4621
movq -0x168(%rbp), %rax
movq %rax, -0xc4(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0xc4(%rbp), %rsi
callq 0x4920
movb %dl, -0x171(%rbp)
movq %rax, -0x170(%rbp)
jmp 0x464e
movb -0x171(%rbp), %al
movq -0x170(%rbp), %rcx
movq %rcx, -0xe8(%rbp)
movb %al, -0xe0(%rbp)
jmp 0x468a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x4b90
jmp 0x48eb
jmp 0x4470
jmp 0x4691
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x435d
jmp 0x46a7
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x42d5
leaq -0x68(%rbp), %rdi
callq 0x49a0
movq %rax, -0xf0(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x49d0
leaq -0x100(%rbp), %rdi
callq 0x49d0
leaq -0x68(%rbp), %rdi
callq 0x4a20
movq %rax, -0x108(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x49f0
testb $0x1, %al
jne 0x4709
jmp 0x48d0
movq -0xf0(%rbp), %rax
movq %rax, -0xf8(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x4a50
leaq -0x68(%rbp), %rdi
callq 0x4a20
movq %rax, -0x110(%rbp)
leaq -0xf8(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x49f0
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x172(%rbp)
jne 0x4757
jmp 0x478c
leaq -0xf0(%rbp), %rdi
callq 0x4a80
movl 0x4(%rax), %eax
movl %eax, -0x178(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x4a80
movq %rax, %rcx
movl -0x178(%rbp), %eax
cmpl (%rcx), %eax
sete %al
movb %al, -0x172(%rbp)
movb -0x172(%rbp), %al
testb $0x1, %al
jne 0x479b
jmp 0x48bd
leaq -0xf0(%rbp), %rdi
callq 0x4aa0
movq (%rax), %rax
movq %rax, -0x118(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x4a80
movl 0x4(%rax), %eax
movl %eax, -0x114(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0x120(%rbp)
movq -0x120(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x4ac0
movq %rax, -0x180(%rbp)
jmp 0x47ed
movq -0x180(%rbp), %rax
movq %rax, -0x128(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0x4b00
movb %dl, -0x189(%rbp)
movq %rax, -0x188(%rbp)
jmp 0x481a
movb -0x189(%rbp), %al
movq -0x188(%rbp), %rcx
movq %rcx, -0x138(%rbp)
movb %al, -0x130(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0x4b50
movq %rax, -0x198(%rbp)
jmp 0x484d
movq -0x198(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0xf8(%rbp), %rax
movq %rax, -0x100(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x4a50
movq -0x100(%rbp), %rax
movq %rax, -0x148(%rbp)
movq -0x148(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x4ac0
movq %rax, -0x1a0(%rbp)
jmp 0x48aa
movq -0x1a0(%rbp), %rax
movq %rax, -0x150(%rbp)
jmp 0x4723
movq -0xf8(%rbp), %rax
movq %rax, -0xf0(%rbp)
jmp 0x46dd
movb $0x1, -0x1(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x4b90
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
movq -0xd0(%rbp), %rdi
callq 0x11d0
nopw (%rax,%rax)