~ubuntu-branches/ubuntu/intrepid/plplot/intrepid

« back to all changes in this revision

Viewing changes to src/plcore.c

  • Committer: Bazaar Package Importer
  • Author(s): Rafael Laboissiere
  • Date: 2006-11-04 10:19:34 UTC
  • mfrom: (2.1.8 edgy)
  • Revision ID: james.westby@ubuntu.com-20061104101934-mlirvdg4gpwi6i5q
Tags: 5.6.1-10
* Orphaning the package
* debian/control: Changed the maintainer to the Debian QA Group

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: plcore.c,v 1.134 2004/06/14 21:51:57 rlaboiss Exp $
 
1
/* $Id: plcore.c,v 1.169 2006/05/27 18:16:01 hbabcock Exp $
2
2
 
3
3
        Central dispatch facility for PLplot.
4
4
        Also contains the PLplot main data structures, external access
8
8
 
9
9
 
10
10
  Copyright (C) 2004  Joao Cardoso
11
 
  Copyright (C) 2004  Rafael Laboissiere
12
 
  Copyright (C) 2004  Andrew Ross
 
11
  Copyright (C) 2004, 2005  Rafael Laboissiere
 
12
  Copyright (C) 2004, 2006  Andrew Ross
 
13
  Copyright (C) 2004  Andrew Roach
 
14
  Copyright (C) 2005  Alan W. Irwin
 
15
  Copyright (C) 2005  Thomas J. Duck
13
16
 
14
17
  This file is part of PLplot.
15
18
 
25
28
 
26
29
  You should have received a copy of the GNU Library General Public License
27
30
  along with PLplot; if not, write to the Free Software
28
 
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
31
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29
32
 
30
33
*/
31
34
 
70
73
enum {AT_BOP, DRAWING, AT_EOP};
71
74
 
72
75
/* Initialize device. */
73
 
/* The plot buffer must be called last */
 
76
/* The plot buffer must be called last. */
 
77
 
 
78
/* The following array of chars is used both here and in plsym.c for
 
79
 * translating the Greek characters from the #g escape sequences into
 
80
 * the Hershey and Unicode codings
 
81
 */
 
82
const char plP_greek_mnemonic[] = "ABGDEZYHIKLMNCOPRSTUFXQWabgdezyhiklmncoprstufxqw";
74
83
 
75
84
void
76
85
plP_init(void)
84
93
}
85
94
 
86
95
/* End of page */
87
 
/* The plot buffer must be called first */
88
 
/* Ignore instruction if there's nothing drawn */
 
96
/* The plot buffer must be called first. */
 
97
/* Ignore instruction if already at eop. */
89
98
 
90
99
void
91
100
plP_eop(void)
92
101
{
93
102
    int skip_driver_eop = 0;
94
103
 
95
 
    if (plsc->page_status != DRAWING)
 
104
    if (plsc->page_status == AT_EOP)
96
105
        return;
97
106
 
98
107
    plsc->page_status = AT_EOP;
110
119
}
111
120
 
112
121
/* Set up new page. */
113
 
/* The plot buffer must be called last */
114
 
/* Ignore if the bop was already issued. */
 
122
/* The plot buffer must be called last. */
 
123
/* Ignore if already at bop. */
115
124
/* It's not actually necessary to be AT_EOP here, so don't check for it. */
116
125
 
117
126
void
163
172
void
164
173
plP_state(PLINT op)
165
174
{
 
175
    if (plsc->plbuf_write) plbuf_state(plsc, op);
 
176
 
166
177
    (*plsc->dispatch_table->pl_state) ((struct PLStream_struct *) plsc, op);
167
 
 
168
 
    if (plsc->plbuf_write)
169
 
        plbuf_state(plsc, op);
170
178
}
171
179
 
172
180
/* Escape function, for driver-specific commands. */
174
182
void
175
183
plP_esc(PLINT op, void *ptr)
176
184
{
177
 
    (*plsc->dispatch_table->pl_esc) ((struct PLStream_struct *) plsc, op, ptr);
178
 
 
179
 
    if (plsc->plbuf_write)
180
 
        plbuf_esc(plsc, op, ptr);
 
185
  PLINT clpxmi, clpxma, clpymi, clpyma;
 
186
  EscText* args;
 
187
 
 
188
  /* The plot buffer must be called first */
 
189
  if(plsc->plbuf_write) plbuf_esc(plsc, op, ptr);
 
190
 
 
191
  /* Text coordinates must pass through the driver interface filter */
 
192
  if(op==PLESC_HAS_TEXT && plsc->dev_unicode) {
 
193
 
 
194
    /* Apply the driver interface filter */
 
195
    if (plsc->difilt) {
 
196
      args = (EscText*)ptr;
 
197
      difilt(&(args->x),&(args->y),1,&clpxmi,&clpxma,&clpymi,&clpyma);
 
198
    }
 
199
  }
 
200
  
 
201
  (*plsc->dispatch_table->pl_esc) ((struct PLStream_struct *) plsc, op, ptr);
181
202
}
182
203
 
183
204
/* Set up plot window parameters. */
351
372
#define DEBUG_TEXT
352
373
*/
353
374
 
 
375
#define hex2dec( a ) isdigit(a) ? a - 48 : (toupper(a) - 65) + 10
 
376
 
 
377
/*--------------------------------------------------------------------------*\
 
378
 *  int text2num( char *text, char end, PLUNICODE *num)
 
379
 *       char *text - pointer to the text to be parsed
 
380
 *       char end   - end character (i.e. ')' or ']' to stop parsing
 
381
 *       PLUNICODE *num - pointer to an PLUNICODE to store the value
 
382
 *
 
383
 *    Function takes a string, which can be either hex or decimal,
 
384
 *    and converts it into an PLUNICODE, stopping at either a null,
 
385
 *    or the character pointed to by 'end'. It is a bit brain-dead,
 
386
 *    and probably should make more checks, but it works.
 
387
\*--------------------------------------------------------------------------*/
 
388
 
 
389
int text2num( const char *text, char end, PLUNICODE *num)
 
390
{
 
391
  int base=10;
 
392
  unsigned short i=0;
 
393
  *num=0;
 
394
 
 
395
  if (text[1]=='x')
 
396
    {
 
397
      base=16;
 
398
      i=2;
 
399
    }
 
400
 
 
401
  while ((text[i]!=end)&&(text[i]!=0))
 
402
    {
 
403
      *num*=base;
 
404
      *num+=hex2dec(text[i]);
 
405
      i++;
 
406
    }
 
407
  return(i);
 
408
}
 
409
 
 
410
/*--------------------------------------------------------------------------*\
 
411
 *  int text2fci( char *text, unsigned char *hexdigit, unsigned char *hexpower)
 
412
 *       char *text - pointer to the text to be parsed
 
413
 *       unsigned char *hexdigit - pointer to hex value that is stored.
 
414
 *       unsigned char *hexpower - pointer to hex power (left shift) that is stored.
 
415
 *
 
416
 *    Function takes a pointer to a string, which is looked up in a table
 
417
 *    to determine the corresponding FCI (font characterization integer)
 
418
 *    hex digit value and hex power (left shift).  All matched strings
 
419
 *    start with "<" and end with the two characters "/>".
 
420
 *    If the lookup succeeds, hexdigit and hexpower are set to the appropriate
 
421
 *    values in the table, and the function returns the number of characters
 
422
 *    in text that are consumed by the matching string in the table lookup.
 
423
 *
 
424
 *    If the lookup fails, hexdigit is set to 0, hexpower is set to and
 
425
 *    impossible value, and the function returns 0.
 
426
\*--------------------------------------------------------------------------*/
 
427
 
 
428
int text2fci( const char *text, unsigned char *hexdigit, unsigned char *hexpower)
 
429
{
 
430
   typedef struct
 
431
     {
 
432
        char *ptext;
 
433
        unsigned char hexdigit;
 
434
        unsigned char hexpower;
 
435
     }
 
436
   TextLookupTable;
 
437
   /* This defines the various font control commands and the corresponding
 
438
    * hexdigit and hexpower in the FCI.
 
439
    */
 
440
#define N_TextLookupTable 10
 
441
   const TextLookupTable lookup[N_TextLookupTable] = {
 
442
        {"<sans-serif/>", PL_FCI_SANS, PL_FCI_FAMILY},
 
443
        {"<serif/>", PL_FCI_SERIF, PL_FCI_FAMILY},
 
444
        {"<monospace/>", PL_FCI_MONO, PL_FCI_FAMILY},
 
445
        {"<script/>", PL_FCI_SCRIPT, PL_FCI_FAMILY},
 
446
        {"<symbol/>", PL_FCI_SYMBOL, PL_FCI_FAMILY},
 
447
        {"<upright/>", PL_FCI_UPRIGHT, PL_FCI_STYLE},
 
448
        {"<italic/>", PL_FCI_ITALIC, PL_FCI_STYLE},
 
449
        {"<oblique/>", PL_FCI_OBLIQUE, PL_FCI_STYLE},
 
450
        {"<medium/>", PL_FCI_MEDIUM, PL_FCI_WEIGHT},
 
451
        {"<bold/>", PL_FCI_BOLD, PL_FCI_WEIGHT}
 
452
   };
 
453
   int i, length;
 
454
   for (i=0; i<N_TextLookupTable; i++) {
 
455
      length = strlen(lookup[i].ptext);
 
456
      if (! strncmp(text, lookup[i].ptext, length)) {
 
457
         *hexdigit = lookup[i].hexdigit;
 
458
         *hexpower = lookup[i].hexpower;
 
459
         return(length);
 
460
      }
 
461
   }
 
462
   *hexdigit = 0;
 
463
   *hexpower = PL_FCI_HEXPOWER_IMPOSSIBLE;
 
464
   return(0);
 
465
}
 
466
 
 
467
PLUNICODE unicode_buffer[1024];
 
468
 
354
469
void
355
470
plP_text(PLINT base, PLFLT just, PLFLT *xform, PLINT x, PLINT y,
356
471
         PLINT refx, PLINT refy, const char *string)
357
472
{
358
 
    if (plsc->dev_text) {
359
 
        EscText args;
360
 
 
361
 
        args.base = base;
362
 
        args.just = just;
363
 
        args.xform = xform;
364
 
        args.x = x;
365
 
        args.y = y;
366
 
        args.refx = refx;
367
 
        args.refy = refy;
 
473
 
 
474
   if (plsc->dev_text) { /* Does the device render it's own text ? */
 
475
      EscText args;
 
476
      short len=0;
 
477
      char skip;
 
478
      unsigned short i,j;
 
479
      PLUNICODE code;
 
480
      char esc;
 
481
      int idx;
 
482
 
 
483
      args.base = base;
 
484
      args.just = just;
 
485
      args.xform = xform;
 
486
      args.x = x;
 
487
      args.y = y;
 
488
      args.refx = refx;
 
489
      args.refy = refy;
 
490
      args.string = string;
 
491
 
 
492
      if (plsc->dev_unicode) { /* Does the device also understand unicode? */
 
493
         PLINT ig;
 
494
         PLUNICODE fci, fcisave;
 
495
         unsigned char hexdigit, hexpower;
 
496
 
 
497
         /* Now process the text string */
 
498
 
 
499
         if (string!=NULL) {        /* If the string isn't blank, then we will 
 
500
                                     * continue 
 
501
                                     */
 
502
 
 
503
            len=strlen(string);     /* this length is only used in the loop 
 
504
                                     * counter, we will work out the length of 
 
505
                                     * the unicode string as we go */
 
506
            plgesc(&esc);
 
507
        
 
508
            /* At this stage we will do some translations into unicode, like 
 
509
             * conversion to Greek , and will save other translations such as 
 
510
             * superscript for the driver to do later on. As we move through 
 
511
             * the string and do the translations, we will get
 
512
             * rid of the esc character sequence, just replacing it with 
 
513
             * unicode.
 
514
             */
 
515
        
 
516
            /* Obtain FCI (font characterization integer) for start of 
 
517
             * string. */
 
518
            plgfci(&fci);
 
519
            for (j=i=0;i<len;i++) {    /* Walk through the string, and convert 
 
520
                                        * some stuff to unicode on the fly */
 
521
               skip=0;
 
522
        
 
523
               if (string[i]==esc) {
 
524
                  switch(string[i+1]) {
 
525
                   case '(':  /* hershey code */
 
526
                     i+=2+text2num(&string[i+2],')',&code);
 
527
                     idx=plhershey2unicode(code);
 
528
                     /* momentarily switch to symbol font. */
 
529
                     fcisave = fci;
 
530
                     plP_hex2fci(PL_FCI_SYMBOL, PL_FCI_FAMILY, &fci);
 
531
                     unicode_buffer[j++]= fci;
 
532
                     unicode_buffer[j++] = \
 
533
                       (PLUNICODE)hershey_to_unicode_lookup_table[idx].Unicode;
 
534
 
 
535
                     /* if unicode_buffer[j-1] corresponds to the escape 
 
536
                      * character must unescape it by appending one more.  
 
537
                      * This will probably always be necessary since it is 
 
538
                      * likely unicode_buffer will always have to contain 
 
539
                      * escape characters that are interpreted by the device 
 
540
                      * driver.
 
541
                      */
 
542
                     if (unicode_buffer[j-1]==esc) unicode_buffer[j++]=esc;
 
543
                     fci = fcisave;
 
544
                     unicode_buffer[j]= fci;
 
545
                     skip=1;
 
546
                     break;
 
547
                
 
548
                   case '[':  /* unicode */
 
549
                     i+=2+text2num(&string[i+2],']',&code);
 
550
                     /* momentarily switch to symbol font. */
 
551
                     fcisave = fci;
 
552
                     plP_hex2fci(PL_FCI_SYMBOL, PL_FCI_FAMILY, &fci);
 
553
                     unicode_buffer[j++]= fci;
 
554
                     unicode_buffer[j++]=code;
 
555
                     /* if unicode_buffer[j-1] corresponds to the escape 
 
556
                      * character must unescape it by appending one more.  
 
557
                      * This will probably always be necessary since it is 
 
558
                      * likely unicode_buffer will always have to contain 
 
559
                      * escape characters that are interpreted by the device 
 
560
                      * driver.
 
561
                      */
 
562
                     if (unicode_buffer[j-1]==esc) unicode_buffer[j++]=esc;
 
563
                     fci = fcisave;
 
564
                     unicode_buffer[j] = fci;
 
565
                     skip=1;
 
566
                     break;
 
567
                
 
568
                   case '<':  /* change font*/
 
569
                     if ('0' <= string[i+2] && string[i+2] <= '9' ) {
 
570
                        i+=2+text2num(&string[i+2],'>', &code);
 
571
                        if (code & PL_FCI_MARK) {
 
572
                           /* code is a complete FCI (font characterization
 
573
                            * integer): change FCI to this value.
 
574
                            */
 
575
                           fci = code;
 
576
                           unicode_buffer[j]=fci;
 
577
                           skip=1;
 
578
                        }
 
579
                        else {
 
580
                           /* code is not complete FCI. Change
 
581
                            * FCI with hex power in rightmost hex
 
582
                            * digit and hex digit value in second rightmost
 
583
                            * hex digit.
 
584
                            */
 
585
                           hexdigit = (code >> 4) & PL_FCI_HEXDIGIT_MASK;
 
586
                           hexpower = code & PL_FCI_HEXPOWER_MASK;
 
587
                           plP_hex2fci(hexdigit, hexpower, &fci);
 
588
                           unicode_buffer[j]=fci;
 
589
                           skip=1;
 
590
                        }
 
591
                     }
 
592
                
 
593
                     else {
 
594
                        i+=text2fci(&string[i+1], &hexdigit, &hexpower);
 
595
                        if (hexpower < 7) {
 
596
                           plP_hex2fci(hexdigit, hexpower, &fci);
 
597
                           unicode_buffer[j]=fci;
 
598
                           skip=1;
 
599
                        }
 
600
                     }
 
601
                     break;
 
602
                
 
603
                   case 'f':  /* Deprecated Hershey-style font change*/
 
604
                   case 'F':  /* Deprecated Hershey-style font change*/
 
605
                     /* We implement an approximate response here so that 
 
606
                      * reasonable results are obtained for unicode fonts, 
 
607
                      * but this method is deprecated and the #<nnn> or
 
608
                      * #<command string> methods should be used instead
 
609
                      * to change unicode fonts in mid-string.
 
610
                      */
 
611
                     fci = PL_FCI_MARK;
 
612
                     if (string[i+2] == 'n') {
 
613
                        /* medium, upright, sans-serif */
 
614
                        plP_hex2fci(PL_FCI_SANS, PL_FCI_FAMILY, &fci);
 
615
                     } else if (string[i+2] == 'r') {
 
616
                        /* medium, upright, serif */
 
617
                        plP_hex2fci(PL_FCI_SERIF, PL_FCI_FAMILY, &fci);
 
618
                     } else if (string[i+2] == 'i') {
 
619
                        /* medium, italic, serif */
 
620
                        plP_hex2fci(PL_FCI_ITALIC, PL_FCI_STYLE, &fci);
 
621
                        plP_hex2fci(PL_FCI_SERIF, PL_FCI_FAMILY, &fci);
 
622
                     } else if (string[i+2] == 's') {
 
623
                        /* medium, upright, script */
 
624
                        plP_hex2fci(PL_FCI_SCRIPT, PL_FCI_FAMILY, &fci);
 
625
                     } else
 
626
                       fci = PL_FCI_IMPOSSIBLE;
 
627
                
 
628
                     if (fci != PL_FCI_IMPOSSIBLE){
 
629
                        i+=2;
 
630
                        unicode_buffer[j] = fci;
 
631
                        skip = 1;
 
632
                     }
 
633
                     break;
 
634
                
 
635
                   case 'g':  /* Greek font */
 
636
                   case 'G':  /* Greek font */
 
637
                     /* Get the index in the lookup table
 
638
                      * 527 = upper case alpha displacement in Hershey Table
 
639
                      * 627 = lower case alpha displacement in Hershey Table
 
640
                      */
 
641
                     /* momentarily switch to symbol font. */
 
642
                     fcisave = fci;
 
643
                     plP_hex2fci(PL_FCI_SYMBOL, PL_FCI_FAMILY, &fci);
 
644
                     unicode_buffer[j++]= fci;
 
645
                     ig = plP_strpos(plP_greek_mnemonic, string[i+2]);
 
646
                     if (ig >= 0) {
 
647
                        if (ig >= 24)
 
648
                          ig = ig + 100 - 24;
 
649
                        idx=plhershey2unicode(ig+527);
 
650
                        unicode_buffer[j++] = \
 
651
                          (PLUNICODE)hershey_to_unicode_lookup_table[idx].Unicode;
 
652
                        i+=2;
 
653
                        skip=1;  /* skip is set if we have copied something 
 
654
                                  * into the unicode table */
 
655
                     }
 
656
                     else {
 
657
                        /* Use "unknown" unicode character if string[i+2] 
 
658
                         * is not in the Greek array.*/
 
659
                        unicode_buffer[j++]=(PLUNICODE)0x00;
 
660
                        i+=2;
 
661
                        skip=1;  /* skip is set if we have copied something 
 
662
                                  * into  the unicode table */
 
663
                     }
 
664
                     fci = fcisave;
 
665
                     unicode_buffer[j]= fci;
 
666
                     break;
 
667
                
 
668
                  }
 
669
               }
 
670
        
 
671
               if (skip==0) {
 
672
                  PLUNICODE unichar = 0;
 
673
#ifdef HAVE_LIBUNICODE
 
674
                  char* ptr = unicode_get_utf8 (string + i, &unichar);
 
675
#else
 
676
                  char* ptr = utf8_to_ucs4 (string + i, &unichar);
 
677
#endif
 
678
                  if (ptr == NULL) {
 
679
                    char buf[80];
 
680
                    strncpy (buf, string, 30);
 
681
                    sprintf (buf, "UTF-8 string is malformed: %s%s",
 
682
                             buf, strlen (string) > 30 ? "[...]" : "");
 
683
                    plabort (buf);
 
684
                  }
 
685
                  unicode_buffer [j] = unichar;
 
686
                  i += ptr - (string + i) - 1;
 
687
 
 
688
                  /* Search for escesc (an unescaped escape) in the input 
 
689
                   * string and adjust unicode_buffer accordingly).
 
690
                   */
 
691
                  if (unicode_buffer[j] == esc && string[i+1] == esc) {
 
692
                    i++;
 
693
                    unicode_buffer[++j] = esc;
 
694
                  }
 
695
               }
 
696
               j++;
 
697
            }
 
698
            if (j > 0) {
 
699
               args.unicode_array_len=j; /* Much easier to set the length than 
 
700
                                          * work it out later :-) */
 
701
               args.unicode_array=&unicode_buffer[0]; /* Get address of the 
 
702
                                                       * unicode buffer (even 
 
703
                                                       * though it is 
 
704
                                                       * currently  static) */
 
705
            } else
 
706
              /* Don't print anything, if there is no unicode to print! */
 
707
              return;
 
708
         }
 
709
      }
 
710
 
 
711
      if (plsc->dev_unicode) {
 
712
        args.string=NULL; /* We are using unicode */
 
713
      }
 
714
      else  {
368
715
        args.string = string;
369
 
 
370
 
        if (plsc->plbuf_write)
371
 
            plbuf_esc(plsc, PLESC_HAS_TEXT, &args);
372
 
 
373
 
        plP_esc(PLESC_HAS_TEXT, &args);
 
716
      }
 
717
 
 
718
      plP_esc(PLESC_HAS_TEXT, &args);
374
719
#ifndef DEBUG_TEXT
375
 
    } else {
 
720
   } else {
376
721
#endif
377
 
        plstr(base, xform, refx, refy, string);
378
 
    }
 
722
      plstr(base, xform, refx, refy, string);
 
723
   }
 
724
}
 
725
 
 
726
/* convert utf8 string to ucs4 unichar */
 
727
static char *
 
728
utf8_to_ucs4(const char *ptr, PLUNICODE *unichar)
 
729
{
 
730
   char tmp;
 
731
   int isFirst = 1;
 
732
   int cnt = 0;
 
733
   
 
734
   do {
 
735
      /* Get next character in string */
 
736
      tmp = *ptr++;
 
737
      if (isFirst) { /* First char in UTF8 sequence */
 
738
         isFirst = 0;
 
739
         /* Determine length of sequence */
 
740
         if ((unsigned char)(tmp & 0x80) == 0x00) { /* single char */
 
741
            *unichar = (unsigned int)tmp & 0x7F;
 
742
            cnt = 0;
 
743
         } else if ((unsigned char)(tmp & 0xE0) == 0xC0) { /* 2 chars */
 
744
            *unichar = (unsigned int)tmp & 0x1F;
 
745
            cnt = 1;
 
746
         } else if ((unsigned char)(tmp & 0xF0) == 0xE0) { /* 3 chars */
 
747
            *unichar = (unsigned char)tmp & 0x0F;
 
748
            cnt = 2;
 
749
         } else if ((unsigned char)(tmp & 0xF8) == 0xF0) { /* 4 chars */
 
750
            *unichar = (unsigned char)tmp & 0x07;
 
751
            cnt = 3;
 
752
         } else if ((unsigned char)(tmp & 0xFC) == 0xF8) { /* 5 chars */
 
753
            *unichar = (unsigned char)tmp & 0x03;
 
754
            cnt = 4;
 
755
         } else if ((unsigned char)(tmp & 0xFE) == 0xFC) { /* 6 chars */
 
756
            *unichar = (unsigned char)tmp & 0x01;
 
757
            cnt = 5;
 
758
         } else { /* Malformed */
 
759
            ptr = NULL;
 
760
            cnt = 0;
 
761
         }
 
762
      } else { /* Subsequent char in UTF8 sequence */
 
763
         if ((unsigned char)(tmp & 0xC0) == 0x80) {
 
764
            *unichar = (*unichar << 6) | ((unsigned int)tmp & 0x3F);
 
765
            cnt--;
 
766
         } else { /* Malformed */
 
767
            ptr = NULL;
 
768
            cnt = 0;
 
769
         }
 
770
      }
 
771
   } while (cnt > 0);
 
772
   return (char *) ptr;
 
773
}
 
774
 
 
775
/* convert ucs4 unichar to utf8 string */
 
776
int
 
777
ucs4_to_utf8(PLUNICODE unichar, char *ptr)
 
778
{
 
779
  unsigned char *tmp;
 
780
  int len;
 
781
 
 
782
  tmp = (unsigned char *)ptr;
 
783
 
 
784
  if ( (unichar & 0xffff80) == 0 ) {  /* single byte */
 
785
    *tmp = (unsigned char) unichar;
 
786
    tmp++;
 
787
    len = 1;
 
788
  }
 
789
  else if ( (unichar & 0xfff800) == 0) { /* two bytes */
 
790
    *tmp = (unsigned char) 0xc0 | (unichar >> 6);
 
791
    tmp++;
 
792
    *tmp = (unsigned char) 0x80 | (unichar & 0x3f);
 
793
    tmp++;
 
794
    len = 2;
 
795
  }
 
796
  else if ( (unichar & 0xff0000) == 0) { /* three bytes */
 
797
    *tmp = (unsigned char) 0xe0 | (unichar >> 12);
 
798
    tmp++;
 
799
    *tmp = (unsigned char) 0x80 | ((unichar >> 6) & 0x3f);
 
800
    tmp++;      
 
801
    *tmp = (unsigned char) 0x80 | (unichar & 0x3f);
 
802
    tmp++;
 
803
    len = 3;
 
804
  }
 
805
  else if ( (unichar & 0xe0000) == 0){ /* four bytes */
 
806
    *tmp = (unsigned char) 0xf0 | (unichar >> 18);
 
807
    tmp++;
 
808
    *tmp = (unsigned char) 0x80 | ((unichar >> 12) & 0x3f);
 
809
    tmp++;      
 
810
    *tmp = (unsigned char) 0x80 | ((unichar >> 6) & 0x3f);
 
811
    tmp++;      
 
812
    *tmp = (unsigned char) 0x80 | (unichar & 0x3f);
 
813
    tmp++;
 
814
    len = 4;
 
815
  }
 
816
  else {  /* Illegal coding */
 
817
    len = 0;
 
818
  }
 
819
  *tmp = '\0';
 
820
 
 
821
  return len;
379
822
}
380
823
 
381
824
static void
382
825
grline(short *x, short *y, PLINT npts)
383
826
{
384
 
    (*plsc->dispatch_table->pl_line) ( (struct PLStream_struct *) plsc,
385
 
                                       x[0], y[0], x[1], y[1] );
 
827
   (*plsc->dispatch_table->pl_line) ( (struct PLStream_struct *) plsc,
 
828
                                      x[0], y[0], x[1], y[1] );
386
829
}
387
830
 
388
831
static void
389
832
grpolyline(short *x, short *y, PLINT npts)
390
833
{
391
 
    (*plsc->dispatch_table->pl_polyline) ( (struct PLStream_struct *) plsc,
392
 
                                           x, y, npts );
 
834
   (*plsc->dispatch_table->pl_polyline) ( (struct PLStream_struct *) plsc,
 
835
                                          x, y, npts );
393
836
}
394
837
 
395
838
static void
396
839
grfill(short *x, short *y, PLINT npts)
397
840
{
398
 
    plsc->dev_npts = npts;
399
 
    plsc->dev_x = x;
400
 
    plsc->dev_y = y;
 
841
   plsc->dev_npts = npts;
 
842
   plsc->dev_x = x;
 
843
   plsc->dev_y = y;
401
844
 
402
 
    (*plsc->dispatch_table->pl_esc) ( (struct PLStream_struct *) plsc,
403
 
                                      PLESC_FILL, NULL );
 
845
   (*plsc->dispatch_table->pl_esc) ( (struct PLStream_struct *) plsc,
 
846
                                     PLESC_FILL, NULL );
404
847
}
405
848
 
406
849
/*--------------------------------------------------------------------------*\
1338
1781
      free_mem(dispatch_table[i]);
1339
1782
    }
1340
1783
    free_mem(dispatch_table);
 
1784
 
 
1785
    plP_FreeDrvOpts();
 
1786
 
1341
1787
    lib_initialized = 0;
1342
1788
}
1343
1789
 
1495
1941
        if (plsc->cmap1 == NULL)
1496
1942
            plscmap1n(0);
1497
1943
    }
 
1944
 
 
1945
    plsc->psdoc = NULL;
1498
1946
}
1499
1947
 
1500
1948
/*--------------------------------------------------------------------------*\
1643
2091
  if (inited == 0) {
1644
2092
    char currdir[256];
1645
2093
 
 
2094
/* AM: getcwd has a somewhat strange status on Windows, its proper
 
2095
   name is _getcwd, this is a problem in the case of DLLs, like with
 
2096
   the Java bindings.
 
2097
*/
 
2098
#ifdef WIN32
 
2099
#define getcwd _getcwd
 
2100
#endif
 
2101
 
1646
2102
    if (getcwd(currdir, 256) == NULL) {
1647
2103
      pldebug("plInBuildTree():", "Not enough buffer space");
1648
2104
    } else if (strncmp(BUILD_DIR, currdir, strlen(BUILD_DIR)) == 0)
1947
2403
            fprintf(stdout, "\nEnter device number or keyword (stream %d): ",
1948
2404
                   (int) ipls);
1949
2405
 
1950
 
        fgets(response, sizeof(response), stdin);
 
2406
        if(!(fgets(response, sizeof(response), stdin))){
 
2407
                plexit("plSelectDev: Failed to process response.");
 
2408
        }
1951
2409
 
1952
2410
    /* First check to see if device keyword was entered. */
1953
2411
    /* Final "\n" in response messes things up, so ignore it.  */
2178
2636
void
2179
2637
c_plspage(PLFLT xp, PLFLT yp, PLINT xleng, PLINT yleng, PLINT xoff, PLINT yoff)
2180
2638
{
 
2639
    if (plsc->level > 0)
 
2640
        plwarn("calling plspage() after plinit() may give unpredictable results");
 
2641
 
2181
2642
    if (xp)
2182
2643
        plsc->xdpi = xp;
2183
2644
    if (yp)
2462
2923
    *p_esc = plsc->esc;
2463
2924
}
2464
2925
 
 
2926
/* Set the FCI (font characterization integer) for unicode-enabled device
 
2927
 * drivers.
 
2928
 */
 
2929
void
 
2930
c_plsfci(PLUNICODE fci)
 
2931
{
 
2932
   /* Always mark FCI as such. */
 
2933
   plsc->fci = fci | PL_FCI_MARK;
 
2934
}
 
2935
 
 
2936
/* Get the FCI (font characterization integer) for unicode-enabled device
 
2937
 * drivers.
 
2938
 */
 
2939
void
 
2940
c_plgfci(PLUNICODE *pfci)
 
2941
{
 
2942
   /* Always mark FCI as such. */
 
2943
   *pfci = plsc->fci | PL_FCI_MARK;
 
2944
}
 
2945
/* Store hex digit value shifted to the left by hexdigit hexadecimal digits
 
2946
 * into pre-existing FCI.
 
2947
 */
 
2948
void
 
2949
plP_hex2fci(unsigned char hexdigit, unsigned char hexpower, PLUNICODE *pfci)
 
2950
{
 
2951
   PLUNICODE mask;
 
2952
   hexpower = hexpower & PL_FCI_HEXPOWER_MASK;
 
2953
   mask = ~ (((PLUNICODE) PL_FCI_HEXDIGIT_MASK) << ((PLUNICODE) 4*hexpower));
 
2954
   *pfci = *pfci & mask;
 
2955
   mask = (((PLUNICODE) (hexdigit & PL_FCI_HEXDIGIT_MASK)) << (4*hexpower));
 
2956
   *pfci = *pfci | mask;
 
2957
}
 
2958
 
 
2959
/* Retrieve hex digit value from FCI that is masked out and shifted to the
 
2960
 * right by hexpower hexadecimal digits. */
 
2961
void
 
2962
plP_fci2hex(PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower)
 
2963
{
 
2964
   PLUNICODE mask;
 
2965
   hexpower = hexpower & PL_FCI_HEXPOWER_MASK;
 
2966
   mask = (((PLUNICODE) PL_FCI_HEXPOWER_MASK) << ((PLUNICODE) (4*hexpower)));
 
2967
   *phexdigit = (unsigned char) ((fci & mask) >>
 
2968
                                 ((PLUNICODE) (4*hexpower)));
 
2969
}
 
2970
 
2465
2971
/* Get the current library version number */
2466
2972
/* Note: you MUST have allocated space for this (80 characters is safe) */
2467
 
 
2468
2973
void
2469
2974
c_plgver(char *p_ver)
2470
2975
{