Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / server / server.cc
blob88733bec95aace17990ea74f310d518fab4bde8a
1 //========================================================================
2 //
3 // server.cc
4 //
5 // Copyright 1999-2002 Emmanuel Lesueur
6 //
7 //========================================================================
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <exec/types.h>
13 #include <dos/dos.h>
14 #undef Object
15 #include "apdf/AComm.h"
16 #include "Object.h"
17 #include "AOutputDev.h"
18 #include "apdf/io_client.h"
20 #define DB(x) //x
22 #undef malloc
23 #undef realloc
24 #undef calloc
25 #undef free
26 #undef new
27 #undef delete
29 extern volatile int *abortFlagPtr;
30 extern volatile int *drawStatePtr;
31 extern int lastDrawState;
32 extern struct Error *errors;
34 void signal_msg();
36 int init(int errors,volatile int*,volatile int*);
37 void use_prefs(int,const char*,size_t,size_t);
38 int get_page_size(PDFDoc*,int page,int* width,int* height,int* rotate);
39 PDFDoc* create_doc(BPTR,const char* filename,int*,const char*,const char*);
40 void delete_doc(PDFDoc*);
41 AOutputDev* create_output_dev(UBYTE *map,int size);
42 void delete_output_dev(AOutputDev*);
43 int simple_find(AOutputDev* aout,const char* str,int top,int* xmin,int* ymin,int* xmax,int* ymax);
44 int init_find(const char*);
45 int find(PDFDoc* doc,int start,int stop,int* xmin,int* ymin,int* xmax,int* ymax,int* page);
46 void end_find();
47 //int chklink(PDFDoc* doc,AOutputDev* aout,int x,int y,Action** action,char* str,size_t len);
48 //int doaction(PDFDoc* doc,AOutputDev* aout,Action** actionp,int* state,int* page,int* x,int* y,char* buf,size_t len);
49 OutputDev* init_write(PDFDoc* doc,const char* filename,int type,int first_page,int last_page,int zoom,int rotate);
50 int writefile(PDFDoc* doc,OutputDev* sv,int first_page,int last_page,int zoom,int rotate);
51 void end_write(OutputDev* sv);
52 char* gettext(AOutputDev*,int,int,int,int);
53 int show_page(AOutputDev*,PDFDoc*,int,int,int,unsigned char*,int,int,int,int,int,int,int,int);
54 void add_fontmap(PDFDoc*,const char*,const char*,int);
55 void clear_fontmap(PDFDoc*);
56 FontOutputDev* init_scan();
57 int scan_fonts(PDFDoc*,FontOutputDev*,int,int);
58 int scan_default_fonts();
59 void end_scan_fonts(FontOutputDev*);
60 int get_font(FontOutputDev*,int,char*,int,char*,int,int*,int*);
61 int has_outlines(PDFDoc* doc);
62 int get_outlines_info(PDFDoc* doc,int* num,size_t* bufsize);
63 void get_outlines(PDFDoc* doc,OutlinesInfo* outlines,size_t bufsize);
64 char* get_doc_info(PDFDoc* doc,size_t*,int*,int*,int*,int*);
65 void get_version(char*,size_t);
66 void set_AA_levels(AOutputDev*,int,int,int);
67 void clear_font_path();
68 void add_font_path(const char *);
69 void get_page_label(PDFDoc*,int,char *,size_t);
70 const char** get_page_labels(PDFDoc*,size_t*,int*);
71 int get_page_index(PDFDoc*,const char *);
72 int get_error(char*,size_t);
73 int get_num_annots(PDFDoc*,int,size_t*);
74 int get_annots(PDFDoc*,AOutputDev*,int,AnnotInfo*,int);
75 Action* set_annot_state(PDFDoc*,Annot*,int);
76 Action* doaction(PDFDoc*,AOutputDev*,Action*,size_t*);
77 int get_events(AOutputDev*,struct ActionInfo*);
78 size_t set_textfield(TextField*,const char*);
79 size_t set_choicefield(ChoiceField*,int,const char*);
80 int import_fdf(PDFDoc*,const char*);
81 int export_fdf(PDFDoc*,const char*);
83 #ifdef DEBUGMEM
84 const char* memalloc_file;
85 int memalloc_line;
86 #endif
88 #ifndef NO_CUSTOM_MEM
89 void* myAllocMem(size_t);
90 void myFreeMem(void*,size_t);
92 struct memchunk {
93 memchunk* next;
94 memchunk* prev;
95 size_t size;
96 size_t free;
99 #ifdef DEBUGMEM
100 static const int begwall=8;
101 static const int endwall=16;
102 #else
103 static const int begwall=0;
104 static const int endwall=0;
105 #endif
107 struct memblock;
109 struct free_node {
110 free_node* next;
111 free_node* prev;
113 void remove() {
114 next->prev=prev;
115 prev->next=next;
116 #ifdef DEBUGMEM
117 next=NULL;
118 prev=NULL;
119 #endif
123 struct free_list {
124 free_node* head;
125 free_node* tail;
126 free_node* tailpred;
128 void addtail(free_node* n) {
129 n->prev=tailpred;
130 n->next=(free_node*)&tail;
131 tailpred->next=n;
132 tailpred=n;
136 struct memblock {
137 size_t size;
138 memblock* pred;
139 #ifdef DEBUGMEM
140 memblock* next;
141 memblock* prev;
142 const char* file;
143 int line;
144 size_t alloc_size;
145 int pad;
146 #endif
148 bool is_free() const { return !(size&1); }
149 bool is_first() const {
150 return pred==NULL;
152 bool is_last() const {
153 return *(size_t*)((char*)(this+1)+begwall+endwall+(size&~1))==0;
155 memblock* succ() const {
156 if(!is_last())
157 return (memblock*)((char*)(this+1)+begwall+endwall+(size&~1));
158 else
159 return NULL;
161 void adjust_successors_pred() {
162 if(memblock* p=succ())
163 p->pred=this;
165 void unlink_free() {
166 ((free_node*)(this+1))->remove();
168 void add_to_freelist(free_list& l) {
169 l.addtail((free_node*)(this+1));
171 void add_to_freelist(free_node& n) {
172 free_node* p=(free_node*)(this+1);
173 p->prev=n.prev;
174 p->next=&n;
175 n.prev->next=p;
176 n.prev=p;
180 memblock* get_memblock(free_node& n) {
181 return (memblock*)&n-1;
184 #ifdef DEBUGMEM
185 extern memblock tail;
186 memblock head={0,0,&tail,NULL};
187 memblock tail={0,0,NULL,&head};
189 int sizes[1000];
190 int bigger;
192 bool check(memblock* p) {
193 bool err=false;
194 unsigned char* t=(unsigned char*)(p+1);
195 for(int k=0;k<begwall;++k)
196 if(*t++!=0x55) {
197 printf("##### block %p (%u,%s,%d): bad header: %02x\n",p,p->size,p->file?p->file:"?",p->line,t[-1]);
198 err=true;
200 t+=p->alloc_size;
201 size_t sz=endwall+(p->size&~1)-p->alloc_size;
202 for(int k=0;k<sz;++k)
203 if(*t++!=0xaa) {
204 printf("##### block %p (%u,%s,%d): bad trailer: %02x\n",p,p->size,p->file?p->file:"?",p->line,t[-1]);
205 err=true;
207 return err;
210 void checkall() {
211 printf("checking memory\n");
212 size_t sz=0;
213 int n=0;
214 for(memblock* p=head.next;p->next;p=p->next) {
215 sz+=p->size&~1;
216 ++n;
217 check(p);
219 printf("%u bytes allocated, %d blocks\n",sz,n);
222 extern "C" void printunfreed() {
223 printf("Unfreed memory:\n");
224 for(memblock* p=head.next;p->next;p=p->next)
225 printf("%x\t%d\t%d\t%s\n",(char*)(p+1)+begwall,p->alloc_size,p->line,p->file?p->file:"?");
226 for(int k=0;k<1000;++k)
227 if(sizes[k]) {
228 printf("sz=%d: %d\n",(k+1)*8,sizes[k]);
230 printf("bigger: %d\n",bigger);
232 #endif
234 struct memlist {
235 memchunk* head;
236 memchunk* tail;
237 memchunk* tailpred;
240 static const int num_small_blocks=1000;
241 static const int num_small_chunks=8;
242 static const size_t block_quantum=8;
243 static const size_t tresh_size=32768;
244 static const size_t puddle_size=128*1024;
245 static const size_t small_puddle_size=16*1024;
246 static free_list small_blocks[num_small_blocks];
247 static free_list big_blocks={(free_node*)&big_blocks.tail,NULL,(free_node*)&big_blocks.head};
248 static memlist chunks={(memchunk*)&chunks.tail,NULL,(memchunk*)&chunks.head};
249 static memlist small_chunks[num_small_chunks];
251 extern "C" int meminit() {
252 for(int k=0;k<num_small_blocks;++k) {
253 small_blocks[k].head=(free_node*)&small_blocks[k].tail;
254 small_blocks[k].tailpred=(free_node*)&small_blocks[k].head;
256 for(int k=0;k<num_small_chunks;++k) {
257 small_chunks[k].head=(memchunk*)&small_chunks[k].tail;
258 small_chunks[k].tailpred=(memchunk*)&small_chunks[k].head;
260 return 0;
263 extern "C" void memcleanup() {
264 memchunk* q=chunks.head;
265 while(q->next) {
266 memchunk* t=q->next;
267 myFreeMem(q,q->size);
268 q=t;
270 for(int k=0;k<num_small_chunks;++k) {
271 memchunk* q=small_chunks[k].head;
272 while(q->next) {
273 memchunk* t=q->next;
274 myFreeMem(q,q->size);
275 q=t;
280 static void free_block(memblock* p) {
281 #ifdef DEBUGMEM
282 if(!p->is_free()) {
283 printf("##### block %p (%u,%s,%d): not free\n",p,p->size,p->file?p->file:"?",p->line);
284 return;
286 #endif
287 if(p->size<=num_small_chunks*block_quantum) {
288 p->add_to_freelist(small_blocks[(p->size-1)/block_quantum]);
289 } else {
290 if(memblock* q=p->pred) {
291 if(q->is_free()) {
292 q->unlink_free();
293 q->size+=p->size+sizeof(memblock)+begwall+endwall;
294 p=q;
295 p->adjust_successors_pred();
298 if(memblock* q=p->succ()) {
299 if(q->is_free()) {
300 q->unlink_free();
301 p->size+=q->size+sizeof(memblock)+begwall+endwall;
302 p->adjust_successors_pred();
305 if(p->is_first() && p->is_last()) {
306 memchunk* q=(memchunk*)p-1;
307 q->next->prev=q->prev;
308 q->prev->next=q->next;
309 myFreeMem(q,q->size);
310 } else {
311 if(p->size<=num_small_blocks*block_quantum) {
312 p->add_to_freelist(small_blocks[(p->size-1)/block_quantum]);
313 } else {
314 free_node* q=big_blocks.head;
315 while(q->next && get_memblock(*q)->size<p->size)
316 q=q->next;
317 p->add_to_freelist(*q);
323 extern "C" void* malloc(size_t sz) {
324 size_t sz2=(sz+7)&~7;
325 memblock* p=NULL;
326 if(sz2==0)
327 sz2=8;
328 if (sz2<=num_small_chunks*block_quantum) {
329 size_t k=(sz2-1)/block_quantum;
330 free_node* q=small_blocks[k].head;
331 if(q->next) {
332 p=get_memblock(*q);
333 p->unlink_free();
334 } else {
335 memchunk* q=small_chunks[k].tailpred;
336 size_t sz3=sz2+sizeof(memblock)+begwall+endwall;
337 if (!q->prev || sz3>q->free) {
338 const size_t chunk_size=small_puddle_size;
339 q=(memchunk*)myAllocMem(chunk_size);
340 if(!q)
341 return NULL;
342 q->next=(memchunk*)&small_chunks[k].tail;
343 q->prev=small_chunks[k].tailpred;
344 small_chunks[k].tailpred->next=q;
345 small_chunks[k].tailpred=q;
346 q->size=chunk_size;
347 q->free=q->size-((sizeof(memchunk)+7)&~7);
349 p=(memblock*)((char*)q+q->size-q->free);
350 p->size=sz2;
351 #ifdef DEBUGMEM
352 p->pred=(memblock*)0xdeadbeef;
353 #endif
354 q->free-=sz3;
356 } else {
357 if(sz2<=num_small_blocks*block_quantum) {
358 size_t k=(sz2-1)/block_quantum;
359 do {
360 free_node* q=small_blocks[k].head;
361 if(q->next) {
362 p=get_memblock(*q);
363 p->unlink_free();
364 break;
366 ++k;
367 } while(k<num_small_blocks);
369 if(!p) {
370 free_node* t=big_blocks.head;
371 while(t->next && get_memblock(*t)->size<sz2)
372 t=t->next;
373 if(t->next) {
374 p=get_memblock(*t);
375 p->unlink_free();
376 } else {
377 size_t chunk_size=sz2+((sizeof(memblock)+begwall+endwall+sizeof(memchunk)+sizeof(size_t)+7)&~7);
378 if(chunk_size<tresh_size)
379 chunk_size=puddle_size;
380 memchunk* q=(memchunk*)myAllocMem(chunk_size);
381 if(!q)
382 return NULL;
383 q->next=(memchunk*)&chunks.tail;
384 q->prev=chunks.tailpred;
385 chunks.tailpred->next=q;
386 chunks.tailpred=q;
387 q->size=chunk_size;
388 q->free=0;
389 chunk_size-=(sizeof(memchunk)+sizeof(size_t)+7)&~7;
390 *(size_t*)((char*)(q+1)+chunk_size)=0;
391 p=(memblock*)(q+1);
392 p->size=chunk_size-sizeof(memblock)-begwall-endwall;
393 p->pred=NULL;
396 if(p->size-sz2>=sizeof(memblock)+begwall+endwall+block_quantum) {
397 memblock* q=(memblock*)((char*)(p+1)+begwall+endwall+sz2);
398 q->size=p->size-sz2-sizeof(memblock)-begwall-endwall;
399 q->pred=p;
400 p->size=sz2;
401 q->adjust_successors_pred();
402 p->size|=1;
403 free_block(q);
406 p->size|=1;
407 #ifdef DEBUGMEM
408 if(sz>p->size-1) {
409 printf("##### invalid block size\n");
410 return NULL;
412 p->alloc_size=sz;
413 if(sz2<=8000) {
414 if(sz2==0)
415 sz2=1;
416 ++sizes[(sz2-1)>>3];
417 } else
418 ++bigger;
419 p->next=&tail;
420 p->prev=tail.prev;
421 p->prev->next=p;
422 tail.prev=p;
423 p->file=memalloc_file;
424 p->line=memalloc_line;
425 memalloc_file=NULL;
426 unsigned char* q=(unsigned char*)(p+1);
427 for(int k=0;k<begwall;++k)
428 *q++=0x55;
429 for(int k=0;k<sz;++k)
430 *q++=0xbb;
431 size_t sz3=endwall+(p->size&~1)-sz;
432 for(int k=0;k<sz3;++k)
433 *q++=0xaa;
434 #endif
435 return (char*)(p+1)+begwall;
438 extern "C" void* calloc(size_t n,size_t sz) {
439 sz*=n;
440 void* p=malloc(sz);
441 if(p && sz)
442 memset(p,0,sz);
443 return p;
446 extern "C" void* realloc(void* t,size_t sz) {
447 if(!t)
448 return malloc(sz);
449 memblock* p=(memblock*)((char*)t-begwall)-1;
450 #ifdef DEBUGMEM
451 check(p);
452 #endif
453 size_t oldsz=p->size&~1;
454 size_t sz2=(sz+7)&~7;
455 if(sz2==0)
456 sz2=8;
457 if(sz2>num_small_chunks*block_quantum && oldsz>num_small_chunks*block_quantum) {
458 if(sz2>oldsz) {
459 if(memblock* q=p->succ()) {
460 if(q->is_free() &&
461 q->size+sizeof(memblock)+begwall+endwall>=sz2-oldsz) {
462 q->unlink_free();
463 oldsz+=q->size+sizeof(memblock)+begwall+endwall;
464 p->size=oldsz;
465 p->adjust_successors_pred();
466 p->size|=1;
467 #ifdef DEBUGMEM
468 unsigned char* t=(unsigned char*)(p+1)+begwall+p->alloc_size;
469 for(int k=0;k<sz-p->alloc_size;++k)
470 *t++=0xbb;
471 p->alloc_size=sz;
472 size_t sz3=endwall+oldsz-sz;
473 for(int k=0;k<sz3;++k)
474 *t++=0xaa;
475 #endif
479 if(sz2<=oldsz) {
480 if(oldsz-sz2>=sizeof(memblock)+begwall+endwall+block_quantum) {
481 memblock* q=(memblock*)((char*)(p+1)+begwall+endwall+sz2);
482 q->size=oldsz-sz2-sizeof(memblock)-begwall-endwall;
483 q->pred=p;
484 p->size=sz2|1;
485 q->adjust_successors_pred();
486 free_block(q);
488 #ifdef DEBUGMEM
489 p->alloc_size=sz;
490 unsigned char* q=(unsigned char*)(p+1)+begwall+sz;
491 size_t sz3=endwall+(p->size&~1)-sz;
492 for(int k=0;k<sz3;++k)
493 *q++=0xaa;
494 #endif
495 return (char*)(p+1)+begwall;
498 void* q=malloc(sz);
499 if(q) {
500 if(oldsz && sz)
501 memcpy(q,t,sz<oldsz?sz:oldsz);
502 free(t);
503 #if 0// def DEBUGMEM
504 unsigned char* r=(unsigned char*)q+oldsz;
505 size_t sz4=sz-oldsz;
506 for(int k=0;k<sz4;++k)
507 *r++=0xbb;
508 #endif
510 return q;
513 extern "C" void free(void* p) {
514 if(p) {
515 memblock* q=(memblock*)((char*)p-begwall)-1;
516 #ifdef DEBUGMEM
517 if(q->is_free() || q->next==NULL || q->prev==NULL) {
518 printf("##### free called at %s/%d\n",memalloc_file,memalloc_line);
519 printf("##### block %p (%u,%s,%d): already freed\n",q,q->size,q->file?q->file:"?",q->line);
520 checkall();
521 memalloc_file=NULL;
522 return;
524 #endif
525 q->size&=~1;
526 #ifdef DEBUGMEM
527 if(check(q))
528 checkall();
529 unsigned char* t=(unsigned char*)(q+1)+begwall;
530 for(int k=0;k<q->alloc_size;++k)
531 *t++=0xdd;
532 q->next->prev=q->prev;
533 q->prev->next=q->next;
534 q->next=NULL;
535 q->prev=NULL;
536 #endif
537 free_block(q);
539 #ifdef DEBUGMEM
540 memalloc_file=NULL;
541 #endif
544 void* operator new (size_t sz) {
545 void* p=malloc(sz);
546 if(!p)
547 throw "Out of memory!";
548 return p;
551 void operator delete (void* p) {
552 free(p);
555 void* operator new [] (size_t sz) {
556 void* p=malloc(sz);
557 if(!p)
558 throw "Out of memory!";
559 return p;
562 void operator delete [] (void* p) {
563 free(p);
565 #endif
567 extern int maxColors;
569 struct comm_info *(*create_comm_info)(size_t);
570 void (*delete_comm_info)(struct comm_info *);
571 int (*exchange_msg)(struct comm_info *,struct msg_base *,size_t,int);
572 //void (*send_msg)(struct comm_info *,void *,size_t,int);
573 void* (*get_msg)(struct server_info *,void **,size_t *,int *);
574 void (*reply_msg)(void *);
576 #if 0
577 class ServColorAllocator : public ColorAllocator {
578 public:
579 ServColorAllocator(int depth);
580 ~ServColorAllocator();
581 virtual Guchar allocate(Gulong);
582 virtual void allocate(int,ColorEntry*);
583 private:
584 comm_info* ci;
587 ServColorAllocator::ServColorAllocator(int depth) {
588 size_t sz=sizeof(ppcmsg_max);
589 if(depth<=8) {
590 size_t sz2=sizeof(msg_getcolors)+sizeof(ColorEntry)*maxColors;
591 if(sz<sz2)
592 sz=sz2;
594 if(!(ci=create_comm_info(sz)))
595 throw "Can't create message & port.";
598 ServColorAllocator::~ServColorAllocator() {
599 delete_comm_info(ci);
602 Guchar ServColorAllocator::allocate(Gulong val) {
603 msg_getcolor* m=(msg_getcolor*)ci->cmddata;
604 m->r=((val>>16)&0xff)*0x01010101;
605 m->g=((val>> 8)&0xff)*0x01010101;
606 m->b=((val>> 0)&0xff)*0x01010101;
607 exchange_msg(ci,&m->base,sizeof(*m),MSGID_GETCOLOR);
608 return Guchar(m->base.success);
611 void ServColorAllocator::allocate(int num,ColorEntry* p) {
612 if(num>maxColors) {
613 printf("too many colors (%d/%d).\n",num,maxColors);
614 return;
616 msg_getcolors* m=(msg_getcolors*)ci->cmddata;
617 m->num=num;
618 memcpy(m->table,p,num*sizeof(ColorEntry));
619 exchange_msg(ci,&m->base,sizeof(*m)-sizeof(m->table[0])+num*sizeof(ColorEntry),MSGID_GETCOLORS);
620 memcpy(p,m->table,num*sizeof(ColorEntry));
621 /*unsigned long* q=m->table;
622 while(--num>=0) {
623 p->index=*q;
624 ++p;
625 q+=4;
628 #endif
631 void server(comm_info *ci) {
632 bool running=true;
633 IoServer io_server = NULL;
634 bool init_ok=false;
635 do {
636 void* msgdat;
637 size_t len;
638 int id;
639 void* msg=get_msg(NULL,&msgdat,&len,&id);
640 DB(printf("-- msg = %d\n",id);)
641 switch(id) {
642 case MSGID_INIT: {
643 msg_init* p=(msg_init*)msgdat;
644 p->base.success=init_ok=(p->version==VMAGIC && initClientIo(io_server=p->io_server) && init(p->errors,p->abort_flag_ptr,p->draw_state_ptr));
645 break;
647 case MSGID_QUIT:
648 running=false;
649 break;
651 case MSGID_GETERROR: {
652 msg_error* p=(msg_error*)msgdat;
653 p->base.success=get_error(p->msg,sizeof(p->msg));
654 break;
656 case MSGID_USEPREFS: {
657 msg_prefs* p=(msg_prefs*)msgdat;
658 use_prefs(p->colors,p->gzipcmd,p->cachesz,p->cacheblocsz);
659 p->base.success=1;
660 break;
662 case MSGID_CREATEDOC: {
663 msg_createdoc* m=(msg_createdoc*)msgdat;
664 m->doc=create_doc(m->dir,m->filename,&m->num_pages,m->ownerpw,m->userpw);
665 m->base.success=m->doc!=NULL;
666 break;
668 case MSGID_DELETEDOC: {
669 msg_deletedoc* m=(msg_deletedoc*)msgdat;
670 delete_doc(m->doc);
671 m->base.success=1;
672 break;
674 case MSGID_PAGESIZE: {
675 msg_pagesize* m=(msg_pagesize*)msgdat;
676 m->base.success=get_page_size(m->doc,m->page,&m->width,&m->height,&m->rotate);
677 break;
679 case MSGID_CREATEOUTPUTDEV: {
680 msg_create_output_dev* m=(msg_create_output_dev*)msgdat;
681 m->out=NULL;
682 //ColorAllocator* colorAllocator=NULL;
683 try {
684 //colorAllocator=new ServColorAllocator(m->depth);
685 //m->out=create_output_dev(colorAllocator);
686 //colorAllocator=NULL;
687 m->out=create_output_dev(m->map,16);
689 catch(const char* msg) {
690 printf("Exception: %s\n", msg);
692 catch(...) {
693 printf("Exception caught.");
695 //delete colorAllocator;
696 m->base.success=m->out!=NULL;
697 break;
699 case MSGID_DELETEOUTPUTDEV: {
700 msg_delete_output_dev* m=(msg_delete_output_dev*)msgdat;
701 delete_output_dev(m->out);
702 m->base.success=1;
703 break;
705 #if 0
706 case MSGID_SETAALEVELS: {
707 msg_setaalevels* m=(msg_setaalevels*)msgdat;
708 set_AA_levels(m->out,m->text,m->stroke,m->fill);
709 m->base.success=1;
710 break;
712 #endif
713 case MSGID_PAGE: {
714 msg_page* m=(msg_page*)msgdat;
715 PDFDoc* doc=m->doc;
716 AOutputDev* aout=m->aout;
717 int n=m->page_num;
718 int z=m->zoom;
719 int r=m->rotate;
720 int x=m->xoffset;
721 int y=m->yoffset;
722 int w=m->width;
723 int h=m->height;
724 int mod=m->modulo;
725 int bpp=m->bpp;
726 int pixfmt=m->pixfmt;
727 int lev=m->level;
728 m->base.success=1;
729 m->base.error=errors!=NULL;
730 *drawStatePtr=lastDrawState=0;
731 reply_msg(msg);
732 msg=get_msg(NULL,&msgdat,&len,&id);
733 DB(printf("-- abort=%d, level=%d\n-- show_page\n",*abortFlagPtr,lev);)
734 lev=show_page(aout,doc,n,z,r,
735 (unsigned char*)msgdat,
736 x,y,w,h,mod,bpp,pixfmt,lev);
737 DB(printf("-- abort=%d, level=%d\n",*abortFlagPtr,lev);)
738 reply_msg(msg);
739 signal_msg();
740 msg=get_msg(NULL,&msgdat,&len,&id);
741 m=(msg_page*)msgdat;
742 m->returned_level=*abortFlagPtr?-1:lev;
743 m->base.success=1;
744 break;
746 #if 0
747 case MSGID_CHKLINK: {
748 msg_chklink* m=(msg_chklink*)msgdat;
749 m->base.success=chklink(m->doc,m->aout,m->x,m->y,&m->action,m->str,sizeof(m->str));
750 break;
752 case MSGID_DOACTION: {
753 msg_doaction* m=(msg_doaction*)msgdat;
754 m->base.success=doaction(m->doc,m->aout,&m->action,&m->state,&m->page,&m->x,&m->y,m->str,sizeof(m->str));
755 break;
757 #endif
758 case MSGID_SIMPLEFIND: {
759 msg_find* m=(msg_find*)msgdat;
760 m->base.success=simple_find(m->aout,m->str,m->top,&m->xmin,&m->ymin,&m->xmax,&m->ymax);
761 break;
763 case MSGID_INITFIND: {
764 msg_find* m=(msg_find*)msgdat;
765 m->base.success=init_find(m->str);
766 break;
768 case MSGID_FIND: {
769 msg_find* m=(msg_find*)msgdat;
770 m->base.success=find(m->doc,m->top,m->bottom,&m->xmin,&m->ymin,&m->xmax,&m->ymax,&m->page);
771 break;
773 case MSGID_ENDFIND:
774 end_find();
775 break;
776 case MSGID_INITWRITE: {
777 msg_write* m=(msg_write*)msgdat;
778 m->savedev=init_write(m->doc,m->filename,m->type,m->first_page,m->last_page,m->zoom,m->rotate);
779 m->base.success=m->savedev!=NULL;
780 break;
782 case MSGID_WRITE: {
783 msg_write* m=(msg_write*)msgdat;
784 writefile(m->doc,m->savedev,m->first_page,m->last_page,m->zoom,m->rotate);
785 m->base.success=1;
786 break;
788 case MSGID_ENDWRITE: {
789 msg_write* m=(msg_write*)msgdat;
790 end_write(m->savedev);
791 m->base.success=1;
792 break;
795 case MSGID_GETTEXT: {
796 msg_gettext* m=(msg_gettext*)msgdat;
797 char* p=gettext(m->aout,m->xmin,m->ymin,m->xmax,m->ymax);
798 m->base.success=p!=NULL;
799 m->base.error=errors!=NULL;
800 if(m->base.success) {
801 m->size=strlen(p);
802 reply_msg(msg);
803 msg=get_msg(NULL,&msgdat,&len,&id);
804 char* q=(char*)msgdat;
805 strncpy(q,p,len-1);
806 q[len-1]='\0';
807 free(p);
808 msgdat=NULL;
810 break;
812 case MSGID_HASOUTLINES: {
813 msg_get_outlines_info* m=(msg_get_outlines_info*)msgdat;
814 m->base.success=has_outlines(m->doc);
815 break;
817 case MSGID_GETOUTLINESINFO: {
818 msg_get_outlines_info* m=(msg_get_outlines_info*)msgdat;
819 m->base.success=get_outlines_info(m->doc,&m->num,&m->bufsize);
820 break;
822 case MSGID_GETOUTLINES: {
823 msg_get_outlines* m=(msg_get_outlines*)msgdat;
824 PDFDoc* doc=m->doc;
825 m->base.success=1;
826 m->base.error=errors!=NULL;
827 reply_msg(msg);
828 msg=get_msg(NULL,&msgdat,&len,&id);
829 get_outlines(doc,(OutlinesInfo*)msgdat,0);
830 msgdat=NULL;
831 break;
833 case MSGID_GETDOCINFO: {
834 msg_getdocinfo* m=(msg_getdocinfo*)msgdat;
835 char* p=get_doc_info(m->doc,(size_t*)&m->size,&m->linearized,&m->encrypted,&m->oktoprint,&m->oktocopy);
836 m->base.success=p!=NULL;
837 m->base.error=errors!=NULL;
838 if(m->base.success) {
839 reply_msg(msg);
840 msg=get_msg(NULL,&msgdat,&len,&id);
841 char* q=(char*)msgdat;
842 memcpy(q,p,m->size>len-1?len-1:m->size);
843 q[len-1]='\0';
844 free(p);
845 msgdat=NULL;
847 break;
849 case MSGID_ADDFONTMAP: {
850 msg_addfontmap* m=(msg_addfontmap*)msgdat;
851 add_fontmap(m->pdfdoc,m->pdffont,m->font,m->type);
852 m->base.success=1;
853 break;
855 case MSGID_CLEARFONTMAP: {
856 msg_addfontmap* m=(msg_addfontmap*)msgdat;
857 clear_fontmap(m->pdfdoc);
858 m->base.success=1;
859 break;
861 case MSGID_ADDFONTPATH: {
862 msg_addfontpath* m=(msg_addfontpath*)msgdat;
863 add_font_path(m->path);
864 m->base.success=1;
865 break;
867 case MSGID_CLEARFONTPATH:
868 clear_font_path();
869 break;
870 case MSGID_INITSCAN: {
871 msg_scan_fonts* m=(msg_scan_fonts*)msgdat;
872 m->out=init_scan();
873 m->base.success=m->out!=NULL;
874 break;
876 case MSGID_SCANFONTS: {
877 msg_scan_fonts* m=(msg_scan_fonts*)msgdat;
878 m->base.success=scan_fonts(m->doc,m->out,m->first_page,m->last_page);
879 break;
881 case MSGID_ENDSCANFONTS: {
882 msg_scan_fonts* m=(msg_scan_fonts*)msgdat;
883 end_scan_fonts(m->out);
884 m->base.success=1;
885 break;
887 case MSGID_GETFONT: {
888 msg_fontmap* m=(msg_fontmap*)msgdat;
889 m->base.success=get_font(m->out,m->m,m->pdffont,sizeof(m->pdffont),m->font,sizeof(m->font),&m->type,&m->flags);
890 break;
892 case MSGID_VERSION: {
893 msg_version* m=(msg_version*)msgdat;
894 get_version(m->version,sizeof(m->version));
895 m->base.success=1;
896 break;
898 #if 0
899 case MSGID_GETPAGELABEL: {
900 msg_pagelabel* m=(msg_pagelabel*)msgdat;
901 get_page_label(m->doc,m->index,m->label,sizeof(m->label));
902 m->base.success=1;
903 break;
905 #endif
906 case MSGID_GETPAGELABELS: {
907 msg_pagelabels* m=(msg_pagelabels*)msgdat;
908 size_t sz;
909 int n;
910 const char** p=get_page_labels(m->doc,&sz,&n);
911 m->size=p?sz:0;
912 m->base.success=1;
913 m->base.error=errors!=NULL;
914 if(m->size) {
915 reply_msg(msg);
916 msg=get_msg(NULL,&msgdat,&len,&id);
917 if(msgdat) {
918 memcpy(msgdat,p,sz);
919 const char** q=(const char**)msgdat;
920 int offset=(char*)msgdat-(char*)p;
921 for(int k=0;k<n;++k)
922 *q+++=offset;
924 gfree(p);
925 msgdat=NULL;
927 break;
929 case MSGID_GETPAGEINDEX: {
930 msg_pagelabel* m=(msg_pagelabel*)msgdat;
931 m->index=get_page_index(m->doc,m->label);
932 m->base.success=m->index!=-1;
933 break;
935 case MSGID_GETANNOTS: {
936 msg_getannots* m=(msg_getannots*)msgdat;
937 PDFDoc* doc=m->doc;
938 AOutputDev* aout=m->aout;
939 int page=m->page;
940 int num=m->num=get_num_annots(doc,page,&m->size);
941 m->base.success=1;
942 m->base.error=errors!=NULL;
943 if(m->num) {
944 reply_msg(msg);
945 msg=get_msg(NULL,&msgdat,&len,&id);
946 if(msgdat)
947 get_annots(doc,aout,page,(AnnotInfo*)msgdat,num);
948 msgdat=NULL;
950 break;
952 case MSGID_SETANNOTSTATE: {
953 msg_setannotstate* m=(msg_setannotstate*)msgdat;
954 m->action=set_annot_state(m->pdfdoc,m->annot,m->state);
955 m->base.success=1;
956 break;
958 case MSGID_DOACTION: {
959 msg_doaction* m=(msg_doaction*)msgdat;
960 m->action=doaction(m->pdfdoc,m->aout,m->action,&m->size);
961 m->base.success=1;
962 break;
964 case MSGID_GETEVENTS: {
965 msg_getevents* m=(msg_getevents*)msgdat;
966 AOutputDev* aout=m->aout;
967 m->base.success=1;
968 m->base.error=errors!=NULL;
969 reply_msg(msg);
970 msg=get_msg(NULL,&msgdat,&len,&id);
971 if(msgdat)
972 get_events(aout,(ActionInfo*)msgdat);
973 msgdat=NULL;
974 break;
976 case MSGID_SETTEXTFIELD: {
977 msg_settextfield* m=(msg_settextfield*)msgdat;
978 m->size=set_textfield(m->field,m->txt);
979 m->base.success=1;
980 break;
982 case MSGID_SETCHOICEFIELD: {
983 msg_setchoicefield* m=(msg_setchoicefield*)msgdat;
984 m->size=set_choicefield(m->field,m->num,m->txt);
985 m->base.success=1;
986 break;
988 case MSGID_IMPORTFDF: {
989 msg_fdf* m=(msg_fdf*)msgdat;
990 m->base.success=import_fdf(m->pdfdoc,m->filename);
991 break;
993 case MSGID_EXPORTFDF: {
994 msg_fdf* m=(msg_fdf*)msgdat;
995 m->base.success=export_fdf(m->pdfdoc,m->filename);
996 break;
998 default:
999 ((msg_base*)msgdat)->error=0;
1000 ((msg_base*)msgdat)->success=0;
1001 break;
1003 if(msgdat)
1004 ((msg_base*)msgdat)->error=errors!=NULL;
1005 DB(printf("-- replying\n");)
1006 reply_msg(msg);
1007 } while(running);
1009 if (init_ok)
1010 ioQuit();
1011 cleanupClientIo(io_server);
1012 #ifndef NO_CUSTOM_MEM
1013 #ifdef DEBUGMEM
1014 checkall();
1015 #endif
1016 #endif