// Copyright (C) 2003-2026, Foxit Software Inc..
// All Rights Reserved.
//
// http://www.foxitsoftware.com
//
// The following code is copyrighted and contains proprietary information and trade secrets of Foxit Software Inc..
// You cannot distribute any part of Foxit PDF Conversion SDK to any third party or general public,
// unless there is a separate license agreement with Foxit Software Inc. which explicitly grants you such rights.
//
// This file contains an example to demonstrate how to use Foxit PDF Conversion SDK to convert Office(Word,Excel or PowerPoint) format files to PDF files .

// Include Foxit PDF Conversion SDK header files.
#if defined(_WIN32) || defined(_WIN64) || (defined(__linux__) && (defined(__i386__) || defined(__x86_64__)))

#if defined(_WIN32) || defined(_WIN64)
#include <direct.h>
#else
#include <sys/stat.h>
#include <wchar.h>
#endif
#include <stdio.h>
#include <stdlib.h>

#include "../../../include/fs_basictypes_c.h"
#include "../../../include/fs_common_c.h"
#include "../../../include/fx_stream_c.h"
#include "../../../include/fs_office2pdf_c.h"

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

#ifndef NULL
#define NULL (void*)0
#endif

#define MAX_FILE_PATH 260

static const char* sn = "P3UzPXKJGf7OHTSbhZ6tlBV431IfR0JhCBZo/XUOrENG7KfnzSYbZQ==";
static const char* key = "LTceEOhprTpgi0mLVrxVJm5hqR99zNi1ZCtecxHwMXEuEdHxIQbDJonAF2d37PmvGSN6/PbNarMuKcHQThgXJNojhT75ZAjj166X09vSA51spwLdwH0ykA+v+q+AsQSod/Ib4LZ0i9BkazwVDe0Odn8crtBo7/+0yc5a/mWzNrFdoDMs17PpYQ0LBc6SKD+CAjTzv5oPSaJPU/IGgA2mJTHqNrgacs6IDVJs8rXuDSKVyRZKni//QpBOMCvxkYg9QhIluwBHkbJYtzCJO7ClQrwXq7CJTK46jB6ZNyGX1UFLX+Jt9U6MbBeNPrNvqMaCxkySz92mp+hIxWaVKfWUMT0o7teeScZif9fA58wixmblBm8FuZ1L1+OP9dfwp73vgd3srp28KBt6xZK+MhltDT6QQZlFcLJulFIPaU3+ZvyvOWrEI8ffd3TGHg7/VA8F2uJpz1inLxBF2+NwK+4uD0zVyvBrLS3Z1VgCh22l1XleaUbpBzjcKt0YMxa4tKJpBKUx9FZwwLCKvEb8DJuZ4PMLRSbLv6MVGzR4EZce0opAPxSHdiaxYMONX1K5HOR4uMH6RuncTAXGjEnNB2El3pk5Gw7+a1SlR2rIEKyTLzV4EXnC3eDSPAIufLlrNA8zUOAPvBaMCjCyMlDospzAf0FJwWVhn12zC3PRzq+kiFijLX+XvenWaAlR26NKMXjqySFXQQMxFtN7+Q9ppdxh05h3C7vXcLnD+eXU/vNOWwV0ymMsomQobDnkR8qrcNJkM3/IysaxaszU+4w2EAtYadZ542+LaSpW8YlvM0HqXdtBG7tx/a0qSBFZxSsr+MQZZzpJFZj3VrEakiwuVRztFGLqudrPYWC0HecrcQLO+SGF0kEcpaNZ+ydmveXlpsaIgwro/mzeZHqxFQ8n3W8xHO2bL5CE6KGLwCMZECgnXbLI7SWfuuWOxlkkbxRW1nFA4/VbLWgR7mC2Ax7R5qZd/q3Pzp8s4L0S2Hym2g/3OdjC4RF7SrXhDRWyAwICE/vKaa1nHDLv8XOiKnzz7jDeFBH2ScbfqovUiArVQyzTXxvQ7qhIxg4LatrBNv4k17p2DIRSP/hZBoFmpUEFGnqm6zC6fbkfkJ/ljbjuoTGziFwNHZ2iX//w1TJOGqDQE3Hd3rHJXWqmzpshXCrn1nn1FhbhePiIirnO12XFR2852ltgN/pQXzrZkjhzcoTTZAd6lSsj10q/8wDvOKG0ITbO34f9iO9XAm/WopOpSP2S2HoyxRJJQqbD/94ZR0Uw";

#if defined(_WIN32) || defined(_WIN64)
static const wchar_t* output_path = L"../output_files/";
static const wchar_t* input_path = L"../input_files/";
#else
static const wchar_t* output_path = L"./output_files/";
static const wchar_t* input_path = L"./input_files/";
#endif

#if defined(_WIN32) || defined(_WIN64)
static const wchar_t* resource_folder_path = L"../../../res/office2pdf";
#else
static const wchar_t* resource_folder_path = L"../../res/office2pdf";
#endif

FS_BOOL is_large_file = FALSE;
FILE* file = NULL;
FILE* filestream = NULL;
int ref = 0;
FS_INT64 cur_pos = 0;



void gOpenFile(FILE** p_file, wchar_t* filename, const char *mode) {
	FS_WSTR wstr;
	FS_BSTR bstr;
	*p_file = NULL;
	if (!p_file || !filename || !mode) return;
	wstr.str = filename;
	wstr.len = wcslen(filename);
	FSDK_WStr_UTF8Encode(&wstr, &bstr);
#if defined(_WIN32) || defined(_WIN64)
	fopen_s(p_file, bstr.str, mode);
#elif defined(__linux__)
	*p_file = fopen(bstr.str, mode);
#endif
	FSDK_BStr_Clear(&bstr);
}

FS_INT64 gGetSize(void* user_data) {
	if (!user_data) return 0;
	if (is_large_file) {
		long long size_long;
#if defined(_WIN32) || defined(_WIN64)
		_fseeki64(file, 0, SEEK_END);
		size_long = _ftelli64(file);
#elif defined(__linux__)
		fseeko(file, 0, SEEK_END);
		size_long = ftello(file);
#endif
		return size_long;
	} else {
		fseek(file, 0, SEEK_END);
		return (FS_INT64)ftell(file);
	}
	return 0;
}

FS_BOOL gReadBlock(void* user_data, void* buffer, FS_INT64 offset, size_t size) {
	if (is_large_file) {
		long long read_size;
#if defined(_WIN32) || defined(_WIN64)
		_fseeki64(file, 0, SEEK_END);
#elif defined(__linux__) || defined(__APPLE__)
		fseeko(file, 0, SEEK_END);
#endif
		read_size = fread(buffer, 1, size, file);
		return read_size == size ? TRUE : FALSE;
	} else {
		if (!file)
			return FALSE;
		if (0 != fseek(file, (long)offset, 0))
			return FALSE;
		if (0 == fread(buffer, size, 1, file))
			return FALSE;
		return TRUE;
	}
	return FALSE;
}

static void gRelease(void* user_data) {
	if (file) {
		fclose(file);
		file = NULL;
	}  
	if (user_data)
		free(user_data);
}

FS_INT64 gGetSizeFileStream(void* user_data) {
	if (!user_data) return 0;
	fseek(filestream, 0, SEEK_END);
	return (FS_INT64)ftell(filestream);
}

FS_BOOL gFlushFileStream(void* user_data) {
	fflush(filestream);
	return TRUE;
}

FS_INT64 gGetPositionFileStream(void* user_data) {
	return cur_pos;
}

FS_BOOL gReadBlockFileStream(void* user_data, void* buffer, FS_INT64 offset, size_t size) {
	if (0 != fseek(filestream, (long)offset, 0))
		return FALSE;
	if (0 == fread(buffer, size, sizeof(char), filestream))
		return FALSE;

	cur_pos = offset + size;
	return TRUE;
}

size_t gReadBlock0FileStream(void* user_data, void* buffer, size_t size) {
	if (gReadBlock(user_data, buffer, gGetSize(user_data), size))
		return size;
	else
		return 0;
}

FS_BOOL gWriteBlockFileStream(void* user_data, const void* buffer, FS_INT64 offset, size_t size) {
	FS_INT64 write_size = 0;
	fseek(filestream, (long)offset, SEEK_SET);
	write_size = fwrite(buffer, sizeof(char), size, filestream);
	if (write_size == size) {
		cur_pos = offset + size;
		return TRUE;
	}
	return FALSE;
}

FSIFX_FileStream* gRetainFileStream(void* user_data) {
	ref++;
	return ((FSStreamCallback*)user_data);
}

FS_BOOL gIsEOFFileStream(void* user_data) {
	fseek(filestream, 0, SEEK_END);
	if (cur_pos < (FS_INT64)ftell(filestream))
		return FALSE;
	return TRUE;
}

void gReleaseFileStream(void* user_data) {
	ref--;
	if (ref > 0) return;

	fclose(filestream);
	free(user_data);
}

int main(int argc, char *argv[]) {
  int err_ret = 0;
  wchar_t output_directory[MAX_FILE_PATH];
  FSErrorCode error_code = e_FSErrSuccess;
  wchar_t output_file[MAX_FILE_PATH];
  wchar_t word_file_path[MAX_FILE_PATH];
  wchar_t excel_file_path[MAX_FILE_PATH];
  wchar_t ppt_file_path[MAX_FILE_PATH];
  wchar_t word_file_path_stream[MAX_FILE_PATH];
  wchar_t excel_file_path_stream[MAX_FILE_PATH];
  wchar_t ppt_file_path_stream[MAX_FILE_PATH];
  FSReaderCallback* callback_filereader_word = NULL;
  FSStreamCallback* callback_filestream_word = NULL;
  FSReaderCallback* callback_filereader_excel = NULL;
  FSStreamCallback* callback_filestream_excel = NULL;
  FSReaderCallback* callback_filereader_ppt = NULL;
  FSStreamCallback* callback_filestream_ppt = NULL;
  FS_BOOL is_susccees;

  FSOffice2PDFSettingData setting_data;
  FSWord2PDFSettingData word_setting_data;
  FSExcel2PDFSettingData excel_setting_data;
#if defined(_WIN32) || defined(_WIN64)
  swprintf_s(output_directory, MAX_FILE_PATH, L"%lsoffice2pdf/", output_path);
  _wmkdir(output_directory);
#else
  swprintf(output_directory, MAX_FILE_PATH - 1, L"%lsoffice2pdf/", output_path);
  FS_WSTR wstr;
  wstr.str = output_directory;
  wstr.len = wcslen(output_directory);
  FS_BSTR bstr;
  FSDK_WStr_UTF8Encode(&wstr, &bstr);
  mkdir(bstr.str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
  FSDK_BStr_Clear(&bstr);
#endif

  error_code = FSDK_Library_Initialize(sn, key);
  if (error_code != e_FSErrSuccess) {
    printf("Library Initialize Error: %d\n", error_code);
    return 1;
  }

  setting_data.resource_folder_path.str = (wchar_t*)resource_folder_path;
  setting_data.resource_folder_path.len = wcslen(resource_folder_path);
  setting_data.is_embed_font = FALSE;
  word_setting_data.is_generate_bookmark = FALSE;
  excel_setting_data.is_output_hidden_worksheets = FALSE;
  excel_setting_data.is_separate_workbook = FALSE;
  excel_setting_data.worksheet_names_array_length = 0;
  excel_setting_data.worksheet_names_array = NULL;
  setting_data.excel_setting_data = excel_setting_data;
  setting_data.word_setting_data = word_setting_data;
  // Conver Word file to PDF file.
  swprintf(word_file_path, MAX_FILE_PATH - 1, L"%lsword.docx", input_path);
  swprintf(output_file, MAX_FILE_PATH - 1, L"%lsword2pdf_result.pdf", output_directory);

  error_code = FSDK_Office2PDF_ConvertFromWord(word_file_path, L"", output_file,setting_data, &is_susccees);
  if (error_code != e_FSErrSuccess) {
    printf("Convert Word file to PDF file failed..Error_Code: %d\n", error_code);
  }
  else {
    printf("Convert Word file to PDF file.\n");
  }

  swprintf(word_file_path_stream, MAX_FILE_PATH - 1, L"%lsword2pdf_stream_result.pdf", output_directory);
  callback_filereader_word = (FSReaderCallback*)malloc(sizeof(FSReaderCallback));
  gOpenFile(&file, word_file_path, "rb");

  callback_filereader_word->user_data = callback_filereader_word;
  callback_filereader_word->ReadBlock = gReadBlock;
  callback_filereader_word->Release = gRelease;
  callback_filereader_word->GetSize = gGetSize;

  callback_filestream_word = (FSStreamCallback*)malloc(sizeof(FSStreamCallback));
  gOpenFile(&filestream, word_file_path_stream, "wb");
  callback_filestream_word->Flush = gFlushFileStream;
  callback_filestream_word->GetPosition = gGetPositionFileStream;
  callback_filestream_word->GetSize = gGetSizeFileStream;
  callback_filestream_word->IsEOF = gIsEOFFileStream;
  callback_filestream_word->WriteBlock = gWriteBlockFileStream;
  callback_filestream_word->ReadBlock = gReadBlockFileStream;
  callback_filestream_word->ReadBlock0 = gReadBlock0FileStream;
  callback_filestream_word->Release = gReleaseFileStream;
  callback_filestream_word->Retain = gRetainFileStream;
  callback_filestream_word->user_data = callback_filestream_word;
  ref = 0;
  cur_pos = 0;
  error_code = FSDK_Office2PDF_ConvertFromWord0(callback_filereader_word, L"", callback_filestream_word, setting_data,&is_susccees);
  if (error_code != e_FSErrSuccess) {
    printf("Convert Word file to PDF file failed..Error_Code: %d\n", error_code);
  }
  else {
    printf("Convert Word file to PDF file.\n");
  }

  // Conver Excel file to PDF file.
  swprintf(excel_file_path, MAX_FILE_PATH, L"%lsexcel.xlsx", input_path);
  swprintf(output_file, MAX_FILE_PATH, L"%lsexcel2pdf_result.pdf", output_directory);
  error_code = FSDK_Office2PDF_ConvertFromExcel(excel_file_path, L"", output_file, setting_data,&is_susccees);
  if (error_code != e_FSErrSuccess) {
    printf("Convert Excel file to PDF file failed.Error_Code:%d\n", error_code);
  }
  else {
    printf("Convert Excel file to PDF file.\n");
  }

  swprintf(excel_file_path_stream, MAX_FILE_PATH - 1, L"%lsexcel2pdf_stream_result.pdf", output_directory);
  callback_filereader_excel = (FSReaderCallback*)malloc(sizeof(FSReaderCallback));
  gOpenFile(&file, excel_file_path, "rb");
  callback_filereader_excel->user_data = callback_filereader_excel;
  callback_filereader_excel->ReadBlock = gReadBlock;
  callback_filereader_excel->Release = gRelease;
  callback_filereader_excel->GetSize = gGetSize;

  callback_filestream_excel = (FSStreamCallback*)malloc(sizeof(FSStreamCallback));
  gOpenFile(&filestream, excel_file_path_stream, "wb");
  callback_filestream_excel->Flush = gFlushFileStream;
  callback_filestream_excel->GetPosition = gGetPositionFileStream;
  callback_filestream_excel->GetSize = gGetSizeFileStream;
  callback_filestream_excel->IsEOF = gIsEOFFileStream;
  callback_filestream_excel->ReadBlock = gReadBlockFileStream;
  callback_filestream_excel->ReadBlock0 = gReadBlock0FileStream;
  callback_filestream_excel->WriteBlock = gWriteBlockFileStream;
  callback_filestream_excel->Release = gReleaseFileStream;
  callback_filestream_excel->Retain = gRetainFileStream;
  callback_filestream_excel->user_data = callback_filestream_excel;
  ref = 0;
  cur_pos = 0;
  error_code = FSDK_Office2PDF_ConvertFromExcel0(callback_filereader_excel, L"", callback_filestream_excel,setting_data, &is_susccees);
  if (error_code != e_FSErrSuccess) {
    printf("Convert Excel file to PDF file failed.Error_Code:%d\n", error_code);
  }
  else {
    printf("Convert Excel file to PDF file.\n");
  }



  // Conver PowerPoint file to PDF file.
  swprintf(ppt_file_path, MAX_FILE_PATH - 1, L"%lspowerpoint.pptx", input_path);
  swprintf(output_file, MAX_FILE_PATH - 1, L"%lsppt2pdf_result.pdf", output_directory);
  error_code = FSDK_Office2PDF_ConvertFromPowerPoint(ppt_file_path, L"", output_file,setting_data, &is_susccees);
  if (error_code != e_FSErrSuccess) {
    printf("Convert PowerPoint file to PDF file failed.Error_Code:%d\n", error_code);
  }
  else {
    printf("Convert PowerPoint file to PDF file.\n");
  }

  swprintf(ppt_file_path_stream, MAX_FILE_PATH - 1, L"%lsppt2pdf_stream_result.pdf", output_directory);
  callback_filereader_ppt = (FSReaderCallback*)malloc(sizeof(FSReaderCallback));
  gOpenFile(&file, ppt_file_path, "rb");
  callback_filereader_ppt->user_data = callback_filereader_ppt;
  callback_filereader_ppt->ReadBlock = gReadBlock;
  callback_filereader_ppt->Release = gRelease;
  callback_filereader_ppt->GetSize = gGetSize;

  callback_filestream_ppt = (FSStreamCallback*)malloc(sizeof(FSStreamCallback));
  gOpenFile(&filestream, ppt_file_path_stream, "wb");
  callback_filestream_ppt->Flush = gFlushFileStream;
  callback_filestream_ppt->GetPosition = gGetPositionFileStream;
  callback_filestream_ppt->GetSize = gGetSizeFileStream;
  callback_filestream_ppt->IsEOF = gIsEOFFileStream;
  callback_filestream_ppt->ReadBlock = gReadBlockFileStream;
  callback_filestream_ppt->ReadBlock0 = gReadBlock0FileStream;
  callback_filestream_ppt->WriteBlock = gWriteBlockFileStream;
  callback_filestream_ppt->Release = gReleaseFileStream;
  callback_filestream_ppt->Retain = gRetainFileStream;
  callback_filestream_ppt->user_data = callback_filestream_ppt;
  ref = 0;
  cur_pos = 0;
  error_code = FSDK_Office2PDF_ConvertFromPowerPoint0(callback_filereader_ppt, L"", callback_filestream_ppt,setting_data, &is_susccees);
  if (error_code != e_FSErrSuccess) {
    printf("Convert PowerPoint file to PDF file failed.Error_Code:%d\n", error_code);
  }
  else {
    printf("Convert PowerPoint file to PDF file.\n");
  }
  FSDK_Library_Release();
  return err_ret;
}





#endif  // #if defined(_WIN32)

