Beispiel #1
0
int PrintList(listPtr List, char *DataFmt)
  /* Print List using DataFmt as the printf() format for Node Data Elements */
{
  int Count;
  listnodePtr Position;
  char OutStr[30];

  if (List == NULL) return LLIST_BADVALUE;
  if (List->Flags & LISTBTREE) return PrintTree(List, DataFmt);

  strcpy(OutStr, "\tHead: ");
  strcat(OutStr, DataFmt);
  strcat(OutStr, "\tTail: ");
  strcat(OutStr, DataFmt);
  strcat(OutStr, "\n");
  printf(OutStr, GetNodeData(List->Head), GetNodeData(List->Tail));

  strcpy(OutStr, "Index: %d\tData: ");
  strcat(OutStr, DataFmt);
  strcat(OutStr, "\n");

  Position = List->Current;
  List->Current = List->Head;
  for (Count = 1; Count <= List->Size; Count++)
    {
      printf(OutStr, Count, GetNodeData(List->Current));
      NextNode(List);
    }
  List->Current = Position;

  return LLIST_NOERROR;
} /* PrintList */
Beispiel #2
0
void GraphicTree(listnodePtr Node, char *DataFmt, int Level)
/* Recursive procedure to print the structure of a binary tree.  From
   example code by Matthew Weathers at Biola University */
{
  int Count;
  char OutStr[30];  

  if (Node != NULL)
    {
      for (Count = 0; Count < Level; Count++)
	printf("\t");
      strcpy(OutStr, "\"");
      strcat(OutStr, DataFmt);
      strcat(OutStr, "\" (left=\"");
      strcat(OutStr, DataFmt);
      strcat(OutStr, "\", right=\"");
      strcat(OutStr, DataFmt);
      strcat(OutStr, "\")\n");
      
      printf(OutStr, GetNodeData(Node),
	     GetNodeData(Node->Prev), GetNodeData(Node->Next));
      GraphicTree(Node->Prev, DataFmt, Level + 1);
      GraphicTree(Node->Next, DataFmt, Level + 1);
    }
}
void showInfo()
{
	//StringList show=InitStringList();
	int i;
	Xref xref;
	for(i=0;i<xrefs->length;i++){
		xref=(Xref)GetNodeData(xrefs,i);
		printf("%d----\n",i+1);
		printf("XrefOffset: %d\n",xref->xrefOffset);
		printf("Prev: %d\n",xref->trailer->Prev);
		printf("XRefStm: %d\n",xref->trailer->XRefStm);
	}
	printf( "----\n");
	printf("InfoAt: %d\n",InfoAt);
	printf("%d xrefs\n", xrefs->length);
	for(i=0;i<xrefs->length;i++){
		xref=(Xref)GetNodeData(xrefs,i);
		printf(	 "%s\n",xref->trailer->Prototype) ;
	}
	printf("PDFInfo:\n");
	printf("Title: ");
	printUnicode(Title);
	printf("\nAuthor: ");
	printUnicode(Author);
	printf("\nSubject: ");
	printUnicode(Subject);
	printf("\nKeywords: ");printUnicode(Keywords);
	printf("\nCreationDate: ");printUnicode(CreationDate);
	printf("\nModDate: ");printUnicode(ModDate);
	printf("\nCreator: ");printUnicode(Creator);
	printf("\nProducer: ");printUnicode(Producer);
	printf("\nAdditive Attributes:\n");
	Attr attr;
	for(i=0;i<Attrs->length;i++){
		attr=(Attr)GetNodeData(Attrs,i);
		printf("%d\t",i+1);
		printUnicode(ReadTagString(attr->Name));
		printf("\t");
		printUnicode(attr->Value);
		printf("\n");
	}
	if(Tail==0)return;
	printf("\nTail Attributes:\n");
	for(i=0;i<Tails->length;i++){
		attr=(Attr)GetNodeData(Tails,i);
		printf("%d\t",i+1);
		printUnicode(ReadTagString(attr->Name));
		printf("\t");
		printUnicode(attr->Value);
		printf("\n");
	}
	/*return show;*/
}
Beispiel #4
0
static void ListCmdFn(cmdScannerADT cs)
{
    scannerADT scanner;
    symtabADT nodeTable;
    graphADT graph;
    nodeADT node, target;

    graph = GetCommandData(cs);
    foreach (node in Nodes(graph)) {
        printf("%s:", (string) GetNodeData(node));
        foreach (target in ConnectedNodes(node)) {
            printf(" %s", (string) GetNodeData(target));
        }
//将int值转化为字符串
LPSTR IntToString(int num)
{
	List list=InitList();
	int sign,i;
	LPSTR output;
	if(num==0)
		return "0";
	sign=num>0?1:-1;
	num=num*sign;
	while(num!=0)
	{
		AddNode(list,(void*)(num%10+48));
		num/=10;
	}
	if(sign==-1)
	{
		AddNode(list,(void*)'-');
	}
	output=(LPSTR)malloc(sizeof(char)*(list->length+1));
	for(i=0;i<list->length;i++)
	{
		*(output+i)=(char)GetNodeData(list,list->length-1-i);
	}
	*(output+i)=0;
	return output;
}
/* Add a node forward */
void AddNodeForward(void)
{
    DoubleLinkedList* pNode = malloc(sizeof(DoubleLinkedList));
    pNode = GetNodeData(pNode);
    if(pNode)
    {
    DoubleLinkedList* pCurrent = pHead;
    if (pHead== NULL)
    {
        pNode->pNext= NULL;
        pNode->pPrevious= NULL;
        pHead=pNode;
    }
    else
    {
      while(pCurrent->pNext!=NULL)
      {
        pCurrent=pCurrent->pNext;
      }
      pCurrent->pNext= pNode;
      pNode->pNext= NULL;
      pNode->pPrevious= pCurrent;
    }
    }
    else
    {
        Error = MEMALLOCERROR;
    }

}
//将StringList中保存的所有字符串组合成为一个字符串
LPSTR StringListGetString(StringList list)
{
	int i,j,k,size=0;
	LPSTR data;
	LPSTR String;
	for(i=0;i<list->length;i++){
		data=(char*)GetNodeData(list,i);
		if(data==0)continue;
		size+=(int)strlen(data);
	}
	String=(char*)malloc(sizeof(char)*(size+1));
	for(i=0,k=0;i<list->length;i++){
		data=(char*)GetNodeData(list,i);
		if(data==0)continue;
		for(j=0;data[j]!=0;j++)
		{
			String[k++]=data[j];
		}
	}
	String[k]=0;
	return String;
}
Beispiel #8
0
void *NextNode(listPtr List)
{
  if (List == NULL) 
    return NULL;

  if (List->Current != NULL)
    List->Current = List->Current->Next;

  if ((List->Flags & LISTFLAGMASK) & LISTCIRCULAR)
    if (List->Current == NULL)
      List->Current = List->Head;

  return GetNodeData(List->Current);
} /* NextNode() */
Beispiel #9
0
void *PrevNode(listPtr List)
{
  if (List == NULL) 
    return NULL;

  if (List->Current != NULL)
    List->Current = List->Current->Prev;

  if ((List->Flags & LISTFLAGMASK) & LISTCIRCULAR)
    if (List->Current == NULL)
      List->Current = List->Tail;

  return GetNodeData(List->Current);
} /* PrevNode() */
Beispiel #10
0
int SplayInsertList(listPtr List, listnodePtr Node)
{
  if (List == NULL) return LLIST_NULL;
  if (Node == NULL) return LLIST_NULL;

  if (List->Head != NULL) /* empty tree? */
    {
      if (SplayList(List, Node->Data) != NULL)
	/* We found this element in the splay tree; this is bad.  Say so... */
	return LLIST_BADVALUE;

      if ((List->compare)(Node->Data, List->Head->Data) > 0)
	{
	  Node->Prev = List->Head;
	  if ((List->compare)(Node->Data, GetNodeData(List->Head->Next)) < 0)
	    {
	      Node->Next = List->Head->Next;
	      List->Head->Next = NULL;
	    }
	}
      else
	{
	  Node->Next = List->Head;
	  if ((List->compare)(Node->Data, GetNodeData(List->Head->Prev)) > 0)
	    {
	      Node->Prev = List->Head->Prev;
	      List->Head->Prev = NULL;
	    }
	}
    }

  List->Head = List->Current = Node;
  List->Size++;

  return LLIST_NOERROR;
} /* SplayInsertList() */
Beispiel #11
0
void *IndexNode(listPtr List, int Index)
{
  int Count;

  if ((List == NULL) ||
      ((List->Flags & LISTFLAGMASK) & LISTBTREE))      
    return NULL;

  if (List->Size < Index)
    return NULL;

  List->Current = List->Head;
  for (Count = 1; Count < Index; Count++)
    List->Current = List->Current->Next;

  return GetNodeData(List->Current);
} /* IndexNode() */
Beispiel #12
0
int DumpList(listPtr List, ListDumpFunc DataDump) 
/* Print List data using the DataDump function for Node Data Elements */
{
  int Count;
  listnodePtr Position;

  if (List == NULL) return LLIST_BADVALUE;

  Position = List->Current;
  List->Current = List->Head;
  
  for (Count = 1; Count <= List->Size; Count++)
    {
      DataDump(GetNodeData(List->Current));    
      NextNode(List);
    }

  List->Current = Position;

  return LLIST_NOERROR;
}
Beispiel #13
0
int     CZiMainFrame::OnClickVerifyResponse(WPARAM wp, LPARAM lp)
{
	Assert(lp);
	VerifyScQuery_t    * pVerifyq = (VerifyScQuery_t *)lp;
	VerifyCcResponse_t   verifyp;

	if(wp == 1)
	{
		if(pVerifyq->nRecvType == Type_ImcFriend)
		{
			Assert(pVerifyq->pSenderNetQInfo && 
				pVerifyq->pSenderNetQInfo->nItemType == Type_ImcFriend);
			CNodeList * pTeamInfo = GetTeamInfo(Team_DefaultNameT);

			Assert(pTeamInfo);
			if(pTeamInfo) 
			{
				pVerifyq->pSenderNetQInfo->strAdminName = Team_DefaultNameA;
				AddItem(pVerifyq->pSenderNetQInfo, pTeamInfo);
			}
		}
	}

	// Msg_ScQueryVerify -> Msg_CsResponseVerify ..??
	verifyp.bIsAgree     = wp == 1 ? 1 : 0;
	verifyp.nSenderId    = MagicId_t(Msg_CsResponseVerify, pVerifyq->nRecvType, pVerifyq->nRecverId);
	verifyp.nRecverId    = MagicId_F(Msg_CsResponseVerify, pVerifyq->nSenderId);
	verifyp.szSenderName = pVerifyq->szRecverNamex;
	verifyp.szRecverName = pVerifyq->szSenderNamex;
	verifyp.nRecvType    = pVerifyq->nRecvType;
	verifyp.pSenderLocalRInfo = GetNodeData(pVerifyq->nRecverId);

	Assert(m_pMainMsger);
	m_pMainMsger->SendImMessage(Msg_CsResponseVerify, (LPARAM)&verifyp, sizeof(verifyp));
	m_pMainMsger->FreeDataEx(Msg_ScQueryVerify, pVerifyq);
	return 0;
}
void AppendTail(List tails)
{
	FILE *fp;
	int i;
	List writer = InitList();

	Tail = hasTail ? Tail : Size;
	AddASCII(writer,IntToString(Tail));
	AddASCII(writer," 0 obj\r\n<<");
	Attr tail;
	for (i=0;i<tails->length;i++)
	{
		tail=(Attr)GetNodeData(tails,i);
		AddASCII(writer,"/");
		AddASCII(writer,tail->Name);
		AddASCII(writer, "(");
		AddBigEndianUnicode(writer, tail->Value);
		AddASCII(writer,")");
	}
	AddASCII(writer, ">>\r\nendobj");
	if (hasTail)
	{
		if((fp=fopen(PDFPath,"wb"))==0)
		{
			printf("cannot open %s\n",PDFPath);
			system("pause");
			exit(0);
		}

		int gap = writer->length - TailEnd + TailAt;
		//更新xrefs
		Xref xref;
		for (i = 0; i < xrefs->length; i++)
		{
			xref=(Xref)GetNodeData(xrefs,i);
			xref->newXrefOffset = xref->xrefOffset;
			xref->newPrev = xref->trailer->Prev;
			if (i > 0)
			{
				xref->newPrev = ((Xref)GetNodeData(xrefs,i-1))->newXrefOffset;
			}
			if (xref->xrefOffset > TailAt)        //未检测位数变化
			{
				xref->newXrefOffset += gap;
			}
			if (xref->trailer->XRefStm > TailAt)
			{
				xref->trailer->XRefStm += gap;
			}
		}
		int newStartxref = xref->newXrefOffset;
		List newXrefs=InitList();
		int j,min,offset=0;
		Xref minOffsetXref;
		for(i=0;i<xrefs->length;i++)//鉴于xref不会很多,暂时用n^2的低效算法
		{
			min=MAXINT;
			for(j=0;j<xrefs->length;j++)
			{
				xref=(Xref)GetNodeData(xrefs,j);
				if(xref->xrefOffset<=offset)continue;
				if(xref->xrefOffset<min){
					min=xref->xrefOffset;
					minOffsetXref=xref;
				}
			}
			offset=minOffsetXref->xrefOffset;
			AddNode(newXrefs,minOffsetXref);
		}
		xrefs=newXrefs;
		int pos = 0;
		for(i=0;i<xrefs->length;i++)   //pos确定Info在Xrefs的排位,指示在哪一个xref之前
		{
			if (((Xref)GetNodeData(xrefs,i))->xrefOffset < TailAt) pos++;
			else break;
		}

		//重写到TailAt,思考能不能直接setlength!!!
		fwrite(PDFInByte,sizeof(char),TailAt,fp);
		//重写Tail
		fwrite(CharListGetString(writer),sizeof(char),writer->length,fp);		
		//写Tail之后,xref之前
		SaveXrefs(fp,TailEnd, gap, pos, xrefs->length, newStartxref,TailAt);

	}
	else
	{
		if((fp=fopen(PDFPath,"ab"))==0)
		{
			printf("cannot open %s\n",PDFPath);
			system("pause");
			exit(0);
		}
		//写Tail前的\r\n
		fputs("\r\n",fp);
		fwrite(CharListGetString(writer),sizeof(char),writer->length,fp);//此处不能fputs!因为有特殊编码方式会被fputs认为是结束符,提前结束
		TailAt = FileLength + 2;//+2因为Tail对象前面补充了\r\n
		TailEnd = TailAt + writer->length;
		Tail = Size;
		fputs("\r\nxref\r\n",fp);
		fputs(IntToString( Tail),fp);
		fputs(" 1\r\n",fp);
		for (i = 0; i < 10 - strlen(IntToString(TailAt)); i++){
			fputs("0",fp);
		}
		fputs(IntToString(TailAt),fp);
		fputs(" 00000 n\r\ntrailer\r\n<</Size ",fp);
		fputs(IntToString(++Size),fp);
		fputs("/Root ",fp);
		fputs(IntToString(Root),fp);
		fputs(" 0 R/Info ",fp);
		fputs(IntToString(Info),fp);				
		fputs( " 0 R/Prev ",fp);
		fputs(IntToString(StartXref),fp);
		fputs( "/Tail ",fp);
		fputs(IntToString(Tail),fp);
		fputs(" 0 R>>\r\nstartxref\r\n",fp);
		fputs(IntToString(TailEnd+2),fp);
		fputs( "\r\n%%EOF",fp);//writer此前保存的是Tail的信息,没有首尾的\r\n

	}
	fclose(fp);
}
int SaveXrefs(FILE *fp, int index, int gap, int from, int to, int newStartxref,int boundary)
{
	List writer = InitList();
	LPSTR str = "";
	int cursor,i,len;
	Xref xref;
	for (cursor = from; cursor < to; cursor++)
	{
		//xref之前
		xref=(Xref)GetNodeData(xrefs,cursor);
		while (index < xref->xrefOffset)
		{
			fputc(PDFInByte[index++],fp);
		}
		//xref地址部分
		while (PDFInByte[index] != 13 && PDFInByte[index] != 10) fputc(PDFInByte[index++],fp);
		while (PDFInByte[index] == 13 || PDFInByte[index] == 10) fputc(PDFInByte[index++],fp);
		len=xref->sections->length;
		Section sec;
		for (i=0;i<len;i++)
		{
			int count,j;
			sec=(Section)GetNodeData(xref->sections,i);
			while (PDFInByte[index] != 13 && PDFInByte[index] != 10)  fputc(PDFInByte[index++],fp);
			while (PDFInByte[index] == 13 || PDFInByte[index] == 10)  fputc(PDFInByte[index++],fp);
			for (count = 0; count < sec->count; count++)
			{
				char Addr[11];
				for (j = 0; j < 10; j++)
				{
					Addr[j] = PDFInByte[index + j];
				}
				Addr[j]=0;
				int num=IntParse(Addr);
				if (num > boundary)
				{
					num += gap;
					for (int j = 0; j < 10; j++)
					{
						Addr[9 - j] = num % 10 + 48;
						num /= 10;
					}
				}
				fputs(Addr,fp);
				index += 10;
				for (j = 0; j < 10; j++)
				{
					fputc(PDFInByte[index++],fp);
				}
			}
		}
		//trailer的处理
		while (PDFInByte[index] != 62 || PDFInByte[index + 1] != 62)
		{
			if (PDFInByte[index] == 80 && PDFInByte[index + 1] == 114 && PDFInByte[index + 2] == 101 && PDFInByte[index + 3] == 118)//Prev
			{
				fputs("Prev ",fp);
				index +=(int)strlen("Prev ");
				str=IntToString(xref->newPrev);
				fputs(str,fp);
				index += (int)strlen(str);
				continue;
			}
			if (PDFInByte[index] == 88 && PDFInByte[index + 1] == 82 && PDFInByte[index + 2] == 101 && PDFInByte[index + 3] == 102)//XRef
			{
				writer=InitList();
				int len = (int)strlen("XRefStm ")+(int)strlen(IntToString(xref->trailer->XRefStm));
				index += len;
				fputs("DelTag ",fp);
				for (i = 0; i < len - 7; i++)fputc('0',fp);
				continue;
			}
			fputc(PDFInByte[index++],fp);
		}//结束时index指向>>的第一个>
		//看是否有startxref
		if (cursor == xrefs->length - 1)
		{
			int see = index + 2;
			while (PDFInByte[see] == 13 || PDFInByte[see] == 10) see++; //结束时指向下一行第一个字符
			//若有start
			if (PDFInByte[see] == 115 && PDFInByte[see + 1] == 116 && PDFInByte[see + 2] == 97 && PDFInByte[see + 3] == 114 && PDFInByte[see + 4] == 116)
			{
				while (PDFInByte[see] < 48 || PDFInByte[see] > 57) see++;//see定位在第一个数字
				while (index < see) fputc(PDFInByte[index++],fp);//结束时index指向第一个数字

				str = IntToString(newStartxref);
				fputs(str,fp);
				index += (int)strlen(str);

				if (cursor == xrefs->length- 1)
				{
					while (index < FileLength)
					{
						fputc(PDFInByte[index++],fp);
					}
					break;
				}
			}
		}
	}
	return index;
}
//读取PDF的信息
void ReadPath(char *PDFPath)
{
	FILE *fp;
	if((fp=fopen(PDFPath,"rb"))==0)
	{
		printf("cannot open %s\n",PDFPath);
	}
	Title=L"";
	Author=L"";
	Subject=L"";
	Keywords=L"";
	CreationDate=L"";
	ModDate=L"";
	Creator=L"";
	Producer=L"";
	xrefs =InitList();
	Tails=InitList();
	Attrs=InitList();
	FileLength=getFileSize(PDFPath);
	printf("FileLength: %d\n",FileLength);
	PDFInByte=(unsigned char*)malloc(sizeof(char)*FileLength);
	fread(PDFInByte,1,FileLength,fp);
	fclose(fp);
	Version[0]=PDFInByte[5];
	Version[1]= '.' ;
	Version[2]=PDFInByte[7];
	Version[3]=0;
	printf("Version: %s\n",Version);

	int index = FileLength;
	index = findStringUp(PDFInByte,FileLength,index, "%%EOF") - 5;
	while (PDFInByte[index] > 57 || PDFInByte[index] < 48) index--;
	int i = 1,j;
	StartXref = 0;

	while (PDFInByte[index] <= 57 && PDFInByte[index] >= 48)
	{
		StartXref += (PDFInByte[index--] - 48) * i;
		i *= 10;
	}
	printf("StartXref: %d\n",StartXref);

	ReadXref(StartXref);

	LPSTR* Addrs=(LPSTR*)malloc(sizeof(char*)*Size);
	Xref xref;
	Section section;
	for(i=0;i<xrefs->length;i++)
	{
		xref=(Xref)GetNodeData(xrefs,i);
		for(j=0;j< xref->sections->length;j++)
		{
			section=(Section)GetNodeData(xref->sections,j);
			for (int cursor = 0; cursor < section->count; cursor++)
			{
				Addrs[section->startID+cursor]=(LPSTR)GetNodeData(section->Addrs,cursor); //用新的覆盖旧的
			}
		}
	}

	//读取Info
	if (Info == 0) return;
	index=InfoAt = IntParse(Substring(Addrs[Info],0, 10));

	while (PDFInByte[index++] != 47) ; //找到第一个/,结束时index指向tag的第一个字符
	List tag = InitList();
	LPSTR tagString;
	LPWSTR valueString;
	valueString=(LPWSTR)malloc(sizeof(wchar_t));
	while (PDFInByte[index] != 62)//>
	{
		//tag.Clear();
		tag = InitList();
		while (PDFInByte[index] != 32 && PDFInByte[index] != 40) //找到空格或者(,结束时index指向空格或(
		{
			AddNode(tag,(void*)PDFInByte[index]);
			index++;
		}
		index = omitBlank(PDFInByte,index);
		tagString =CharListGetString(tag);
		//开始读取value
		if (PDFInByte[index] != 40)                     //指向其他obj的情况
		{
			int tagID = getNumber(PDFInByte, &index);
			index++;
			while (PDFInByte[index] != 47 && PDFInByte[index] != 62) index++;             //找下一个/或者结束符>,结束时index指向下一个/或结束符>

			char *tagAddr = Substring(Addrs[tagID],0, 10);
			int cursor = IntParse(tagAddr);

			while (PDFInByte[cursor++] != 40) ;          //找(,结束时指向属性的第一个字符
			ReadValue(cursor,&valueString);
		}
		else  //跟随的括号中有属性的情况
		{
			index = ReadValue(++index, &valueString) + 1;            //index此时指向)后面一个字符
			while (PDFInByte[index] != 47 && PDFInByte[index] != 62) index++;             //找下一个/或者结束符>,结束时index指向下一个/或结束符>
		}
		index++;
		//index最终定位在下一个tag的第一个字符或结束符>

		int TagNum=-1,i;
		for(i=0;i<8;i++)
		{
			if(strcmp(tagString,InfoTags[i])==0)
			{
				TagNum=i;
				break;
			}
		}
		switch (TagNum)
		{
		case 0: Title = valueString; break;//Title
		case 1: Author = valueString; break;//Author
		case 2: Subject = valueString; break;//Subject
		case 3: Keywords = valueString; break;//Keywords
		case 4: CreationDate = valueString; break;
		case 5: ModDate =valueString; break;//ModDate
		case 6: Creator = valueString; break;//Creator
		case 7: Producer = valueString; break;//Producer
		default: 
			Attr attr=(Attr)malloc(sizeof(_Attr));
			attr->Name=tagString;
			attr->Value=valueString;
			AddNode(Attrs,attr); break;
		}
	}
	while (PDFInByte[index] != 106) index++;//将index指向endobj的j
	InfoEnd = index + 1;


	//读取Tail
	if (Tail == 0) return;
	index=TailAt = IntParse(Substring(Addrs[Tail],0, 10));


	while (PDFInByte[index++] != 47) ; //找到第一个/,结束时index指向tag的第一个字符
	while (PDFInByte[index] != 62)//>
	{
		//tag.Clear();
		tag=InitList();
		while (PDFInByte[index] != 32 && PDFInByte[index] != 40) //找到空格或者(,结束时index指向空格或(
		{
			AddNode(tag,(void*)PDFInByte[index]);
			index++;
		}
		index = omitBlank(PDFInByte,index);
		tagString =CharListGetString(tag);

		//开始读取value,默认Tail的属性只以空号的形式保存
		index = ReadValue(++index, &valueString) + 1;             //index此时指向)后面一个字符
		while (PDFInByte[index] != 47 && PDFInByte[index] != 62) index++;             //找下一个/或者结束符>,结束时index指向下一个/或结束符>

		index++;
		//index最终定位在下一个tag的第一个字符或结束符>
		Attr tail=(Attr)malloc(sizeof(_Attr));
		tail->Name=tagString;
		tail->Value=valueString;
		AddNode(Tails,tail); 
	}
	while (PDFInByte[index] != 106) index++;//将index指向endobj的j
	TailEnd = index + 1;
	fclose(fp);//已经关闭过了?
}
//保存Info和自定义属性
void SaveInfo(LPWSTR title, LPWSTR author, LPWSTR subject, LPWSTR keywords, List attrs)
{
	FILE *fp;
	if((fp=fopen(PDFPath,"wb"))==0)
	{
		printf("cannot open %s\n",PDFPath);
		system("pause");
		exit(0);
	}
	List writer = InitList();
	LPSTR str;
	//生成新的Info
	AddASCII(writer, IntToString(Info));
	AddASCII(writer, " 0 obj\r\n<</Title(");
	AddBigEndianUnicode(writer, title);
	AddASCII(writer, ")/Author(");
	AddBigEndianUnicode(writer, author);
	AddASCII(writer, ")/Subject(");
	AddBigEndianUnicode(writer, subject);
	AddASCII(writer, ")/Keywords(");
	AddBigEndianUnicode(writer, keywords);
	AddASCII(writer, ")/CreationDate(");
	AddASCII(writer, WCharToMByte(CreationDate));
	AddASCII(writer, ")/ModDate(");
	AddASCII(writer, WCharToMByte(ModDate));
	AddASCII(writer, ")/Creator(");
	AddBigEndianUnicode(writer, Creator);
	AddASCII(writer, ")/Producer(");
	AddBigEndianUnicode(writer, Producer);
	int i;
	Attr attr;
	for(i=0;i<attrs->length;i++)
	{
		attr=(Attr)GetNodeData(attrs,i);
		AddASCII(writer, ")/");
		AddASCII(writer, attr->Name);
		AddASCII(writer, "(");
		AddBigEndianUnicode(writer, attr->Value);
	}
	AddASCII(writer, ")>>\r\nendobj");


	int index = 0;
	int pointA = InfoAt;
	int pointB = InfoEnd;
	int gap = writer->length - pointB + pointA;
	//更新xrefs
	Xref xref;
	for (i = 0; i < xrefs->length; i++)
	{
		xref=(Xref)GetNodeData(xrefs,i);
		xref->newXrefOffset = xref->xrefOffset;
		xref->newPrev = xref->trailer->Prev;
		if (i > 0)
		{
			xref->newPrev = ((Xref)GetNodeData(xrefs,i-1))->newXrefOffset;
		}
		if (xref->xrefOffset > pointA)        //未检测位数变化
		{
			xref->newXrefOffset += gap;
		}
		if (xref->trailer->XRefStm > pointA)
		{
			xref->trailer->XRefStm += gap;
		}
	}
	int newStartxref = xref->newXrefOffset;
	List newXrefs=InitList();
	int j,min,offset=0;
	Xref minOffsetXref;
	for(i=0;i<xrefs->length;i++)//鉴于xref不会很多,暂时用n^2的低效算法
	{
		min=MAXINT;
		for(j=0;j<xrefs->length;j++)
		{
			xref=(Xref)GetNodeData(xrefs,j);
			if(xref->xrefOffset<=offset)continue;
			if(xref->xrefOffset<min){
				min=xref->xrefOffset;
				minOffsetXref=xref;
			}
		}
		offset=minOffsetXref->xrefOffset;
		AddNode(newXrefs,minOffsetXref);
	}
	xrefs=newXrefs;
	int pos = 0;
	for(i=0;i<xrefs->length;i++)   //pos确定Info在Xrefs的排位,指示在哪一个xref之前
	{
		if (((Xref)GetNodeData(xrefs,i))->xrefOffset < pointA) pos++;
		else break;
	}

	index=SaveXrefs(fp, index, gap, 0, pos, newStartxref,InfoAt);
	//写到Info之前,此处不能fwrite因为起始点不为0
	while (index < pointA)
	{
		fputc(PDFInByte[index++],fp);
	}
	//重写Info
	fwrite(CharListGetString(writer),sizeof(char),writer->length,fp);
	//写Info之后
	index = pointB;
	index=SaveXrefs(fp,index, gap, pos, xrefs->length, newStartxref,InfoAt);
	fclose(fp);
}