Exemplo n.º 1
0
FXbool ID3V2::parse_text(FXint encoding,const FXchar * buffer,FXint length,FXString & text){
  switch(encoding) {

    case ISO_8859_1 :
      {
        FX88591Codec codec;
        FXint n = codec.mb2utflen(buffer,length);
        if (n>0) {
          text.length(n);
          codec.mb2utf(text.text(),text.length(),buffer,length);
          }
      } break;

    case UTF16_BOM  :
      {
        FXUTF16Codec codec;
        FXint n = codec.mb2utflen(buffer,length);
        if (n>0) {
          text.length(n);
          codec.mb2utf(text.text(),text.length(),buffer,length);
          }
      } break;

    case UTF16      :
      {
        FXUTF16BECodec codec;
        FXint n = codec.mb2utflen(buffer,length);
        if (n>0) {
          text.length(n);
          codec.mb2utf(text.text(),text.length(),buffer,length);
          }

      } break;

    case UTF8      :
      {
        FXUTF8Codec codec;
        FXint n = codec.mb2utflen(buffer,length);
        if (n>0) {
          text.length(n);
          codec.mb2utf(text.text(),text.length(),buffer,length);
          }

      } break;
    default: return false;
    }
  return true;
  }
Exemplo n.º 2
0
// Somebody wants our clipped text
long TextLabel::onClipboardRequest(FXObject* sender,FXSelector sel,void* ptr)
{
    FXEvent *event=(FXEvent*)ptr;
    FXString string;

    // Perhaps the target wants to supply its own data for the clipboard
    if (FXFrame::onClipboardRequest(sender,sel,ptr))
    	return 1;

    // Recognize the request?
    if (event->target==stringType || event->target==textType || event->target==utf8Type || event->target==utf16Type)
    {

        // Get clipped string
        string=clipped;

        // If password mode, replace by stars
        if (options&TEXTFIELD_PASSWD)
        	string.assign('*',string.count());

        // Return clipped text as as UTF-8
        if (event->target==utf8Type)
        {
            setDNDData(FROM_CLIPBOARD,event->target,string);
            return 1;
        }

        // Return clipped text translated to 8859-1
        if (event->target==stringType || event->target==textType)
        {
            FX88591Codec ascii;
            setDNDData(FROM_CLIPBOARD,event->target,ascii.utf2mb(string));
            return 1;
        }

        // Return text of the selection translated to UTF-16
        if (event->target==utf16Type)
        {
            FXUTF16LECodec unicode;             // FIXME maybe other endianness for unix
            setDNDData(FROM_CLIPBOARD,event->target,unicode.utf2mb(string));
            return 1;
        }
    }
    return 0;
}
Exemplo n.º 3
0
void SaveToPDF(SciDoc*sci,  FILE *fp)
{
  // This class conveniently handles the tracking of PDF objects
  // so that the cross-reference table can be built (PDF1.4Ref(p39))
  // All writes to fp passes through a PDFObjectTracker object.
  class PDFObjectTracker {
  private:
    FILE *fp;
    int *offsetList, tableSize;
  public:
    int index;
    PDFObjectTracker(FILE *fp_) {
      fp = fp_;
      tableSize = 100;
      offsetList = new int[tableSize];
      index = 1;
    }
    ~PDFObjectTracker() {
      delete []offsetList;
    }
    void write(const char *objectData) {
      unsigned int length = strlen(objectData);
      // note binary write used, open with "wb"
      fwrite(objectData, sizeof(char), length, fp);
    }
    void write(int objectData) {
      char val[20];
      sprintf(val, "%d", objectData);
      write(val);
    }
    // returns object number assigned to the supplied data
    int add(const char *objectData) {
      // resize xref offset table if too small
      if (index > tableSize) {
        int newSize = tableSize * 2;
        int *newList = new int[newSize];
        for (int i = 0; i < tableSize; i++) {
          newList[i] = offsetList[i];
        }
        delete []offsetList;
        offsetList = newList;
        tableSize = newSize;
      }
      // save offset, then format and write object
      offsetList[index - 1] = ftell(fp);
      write(index);
      write(" 0 obj\n");
      write(objectData);
      write("endobj\n");
      return index++;
    }
    // builds xref table, returns file offset of xref table
    int xref() {
      char val[32];
      // xref start index and number of entries
      int xrefStart = ftell(fp);
      write("xref\n0 ");
      write(index);
      // a xref entry *must* be 20 bytes long (PDF1.4Ref(p64))
      // so extra space added; also the first entry is special
      write("\n0000000000 65535 f \n");
      for (int i = 0; i < index - 1; i++) {
        sprintf(val, "%010d 00000 n \n", offsetList[i]);
        write(val);
      }
      return xrefStart;
    }
  };

  // Object to manage line and page rendering. Apart from startPDF, endPDF
  // everything goes in via add() and nextLine() so that line formatting
  // and pagination can be done properly.
  class PDFRender {
  private:
    bool pageStarted;
    bool firstLine;
    int pageCount;
    int pageContentStart;
    double xPos, yPos;  // position tracking for line wrapping
    FXString pageData;  // holds PDF stream contents
    FXString segment;  // character data
    char *segStyle;    // style of segment
    bool justWhiteSpace;
    int styleCurrent, stylePrev;
    double leading;
    char *buffer;
  public:
    PDFObjectTracker *oT;
    PDFStyle *style;
    int fontSize;    // properties supplied by user
    int fontSet;
    int pageWidth, pageHeight;
    PRectangle pageMargin;
    //
    PDFRender() {
      pageStarted = false;
      pageCount = 0;
      style = NULL;
      buffer = new char[250];
      segStyle = new char[100];
    }
    ~PDFRender() {
      if (style) { delete []style; }
      delete []buffer;
      delete []segStyle;
    }
    //
    double fontToPoints(int thousandths) {
      return (double)fontSize * thousandths / 1000.0;
    }
    void setStyle(char *buff, int style_) {
      int styleNext = style_;
      if (style_ == -1) { styleNext = styleCurrent; }
      *buff = '\0';
      if (styleNext != styleCurrent || style_ == -1) {
        if (style[styleCurrent].font != style[styleNext].font
                || style_ == -1) {
          sprintf(buff, "/F%d %d Tf ",
                  style[styleNext].font + 1, fontSize);
        }
        if (strcmp(style[styleCurrent].fore, style[styleNext].fore) != 0
                || style_ == -1) {
          strcat(buff, style[styleNext].fore);
          strcat(buff, "rg ");
        }
      }
    }
    //
    void startPDF() {
      if (fontSize <= 0) {
        fontSize = PDF_FONTSIZE_DEFAULT;
      }
      // leading is the term for distance between lines
      leading = fontSize * PDF_SPACING_DEFAULT;
      // sanity check for page size and margins
      int pageWidthMin = (int)leading + pageMargin.left + pageMargin.right;
      if (pageWidth < pageWidthMin) {
        pageWidth = pageWidthMin;
      }
      int pageHeightMin = (int)leading + pageMargin.top + pageMargin.bottom;
      if (pageHeight < pageHeightMin) {
        pageHeight = pageHeightMin;
      }
      // start to write PDF file here (PDF1.4Ref(p63))
      // ASCII>127 characters to indicate binary-possible stream
      oT->write("%PDF-1.3\n%\xc7\xec\x8f\xa2\n");
      styleCurrent = STYLE_DEFAULT;

      // build objects for font resources; note that font objects are
      // *expected* to start from index 1 since they are the first objects
      // to be inserted (PDF1.4Ref(p317))
      for (int i = 0; i < 4; i++) {
        sprintf(buffer, "<</Type/Font/Subtype/Type1"
                "/Name/F%d/BaseFont/%s/Encoding/"
                PDF_ENCODING
                ">>\n", i + 1,
                PDFfontNames[fontSet * 4 + i]);
        oT->add(buffer);
      }
      pageContentStart = oT->index;
    }
    void endPDF() {
      if (pageStarted) {  // flush buffers
        endPage();
      }
      // refer to all used or unused fonts for simplicity
      int resourceRef = oT->add(
                  "<</ProcSet[/PDF/Text]\n"
                  "/Font<</F1 1 0 R/F2 2 0 R/F3 3 0 R"
                  "/F4 4 0 R>> >>\n");
      // create all the page objects (PDF1.4Ref(p88))
      // forward reference pages object; calculate its object number
      int pageObjectStart = oT->index;
      int pagesRef = pageObjectStart + pageCount;
      for (int i = 0; i < pageCount; i++) {
        sprintf(buffer, "<</Type/Page/Parent %d 0 R\n"
                "/MediaBox[ 0 0 %d %d"
                "]\n/Contents %d 0 R\n"
                "/Resources %d 0 R\n>>\n",
                pagesRef, pageWidth, pageHeight,
                pageContentStart + i, resourceRef);
        oT->add(buffer);
      }
      // create page tree object (PDF1.4Ref(p86))
      pageData = "<</Type/Pages/Kids[\n";
      for (int j = 0; j < pageCount; j++) {
        sprintf(buffer, "%d 0 R\n", pageObjectStart + j);
        pageData += buffer;
      }
      sprintf(buffer, "]/Count %d\n>>\n", pageCount);
      pageData += buffer;
      oT->add(pageData.text());
      // create catalog object (PDF1.4Ref(p83))
      sprintf(buffer, "<</Type/Catalog/Pages %d 0 R >>\n", pagesRef);
      int catalogRef = oT->add(buffer);
      // append the cross reference table (PDF1.4Ref(p64))
      int xref = oT->xref();
      // end the file with the trailer (PDF1.4Ref(p67))
      sprintf(buffer, "trailer\n<< /Size %d /Root %d 0 R\n>>"
              "\nstartxref\n%d\n%%%%EOF\n",
              oT->index, catalogRef, xref);
      oT->write(buffer);
    }
    void add(char ch, int style_) {
      if (!pageStarted) {
        startPage();
      }
      // get glyph width (TODO future non-monospace handling)
      double glyphWidth = fontToPoints(PDFfontWidths[fontSet]);
      xPos += glyphWidth;
      // if cannot fit into a line, flush, wrap to next line
      if (xPos > pageWidth - pageMargin.right) {
        nextLine();
        xPos += glyphWidth;
      }
      // if different style, then change to style
      if (style_ != styleCurrent) {
        flushSegment();
        // output code (if needed) for new style
        setStyle(segStyle, style_);
        stylePrev = styleCurrent;
        styleCurrent = style_;
      }
      // escape these characters
      if (ch == ')' || ch == '(' || ch == '\\') {
        segment += '\\';
      }
      if (ch != ' ') { justWhiteSpace = false; }
      segment += ch;  // add to segment data
    }
    void flushSegment() {
      if (segment.length() > 0) {
        if (justWhiteSpace) {  // optimise
          styleCurrent = stylePrev;
        } else {
          pageData += segStyle;
        }
        pageData += "(";
        pageData += segment;
        pageData += ")Tj\n";
      }
      segment.clear();
      *segStyle = '\0';
      justWhiteSpace = true;
    }
    void startPage() {
      pageStarted = true;
      firstLine = true;
      pageCount++;
      double fontAscender = fontToPoints(PDFfontAscenders[fontSet]);
      yPos = pageHeight - pageMargin.top - fontAscender;
      // start a new page
      sprintf(buffer, "BT 1 0 0 1 %d %d Tm\n",
              pageMargin.left, (int)yPos);
      // force setting of initial font, colour
      setStyle(segStyle, -1);
      strcat(buffer, segStyle);
      pageData = buffer;
      xPos = pageMargin.left;
      segment.clear();
      flushSegment();
    }
    void endPage() {
      pageStarted = false;
      flushSegment();
      // build actual text object; +3 is for "ET\n"
      // PDF1.4Ref(p38) EOL marker preceding endstream not counted
      char *textObj = new char[pageData.length() + 100];
      // concatenate stream within the text object
      sprintf(textObj, "<</Length %d>>\nstream\n%s"
              "ET\nendstream\n",
              static_cast<int>(pageData.length() - 1 + 3),
              pageData.text());
      oT->add(textObj);
      delete []textObj;
    }
    void nextLine() {
      if (!pageStarted) {
        startPage();
      }
      xPos = pageMargin.left;
      flushSegment();
      // PDF follows cartesian coords, subtract -> down
      yPos -= leading;
      double fontDescender = fontToPoints(PDFfontDescenders[fontSet]);
      if (yPos < pageMargin.bottom + fontDescender) {
        endPage();
        startPage();
        return;
      }
      if (firstLine) {
        // avoid breakage due to locale setting
        int f = (int)(leading * 10 + 0.5);
        sprintf(buffer, "0 -%d.%d TD\n", f / 10, f % 10);
        firstLine = false;
      } else {
        sprintf(buffer, "T*\n");
      }
      pageData += buffer;
    }
  };
  PDFRender pr;

  sci->sendMessage(SCI_COLOURISE, 0, -1);
  int tabSize = PDF_TAB_DEFAULT;

  pr.fontSize = 0;

  FXString propItem = "Courier";
  pr.fontSet = PDF_FONT_DEFAULT;
  if (propItem.length()) {
    if (propItem == "Courier")
      pr.fontSet = 0;
    else if (propItem == "Helvetica")
      pr.fontSet = 1;
    else if (propItem == "Times")
      pr.fontSet = 2;
  }

  pr.pageWidth = PDF_WIDTH_DEFAULT;
  pr.pageHeight = PDF_HEIGHT_DEFAULT;
  pr.pageMargin.left = PDF_MARGIN_DEFAULT;
  pr.pageMargin.right = PDF_MARGIN_DEFAULT;
  pr.pageMargin.top = PDF_MARGIN_DEFAULT;
  pr.pageMargin.bottom = PDF_MARGIN_DEFAULT;

  // collect all styles available for that 'language'
  // or the default style if no language is available...
  pr.style = new PDFStyle[STYLE_MAX + 1];

  LangStyle* ls = sci->getLanguage();
  if (ls) {
    StyleDef* sd;
    int i;
    for (i=0; (i<=STYLE_MAX); i++) {  // get keys
     sd=GetStyleFromId(ls->styles, i);
     if (!sd) { sd=Settings::globalStyle(); }

      pr.style[i].font = 0;
      if (sd->style & Italic) { pr.style[i].font |= 2; }
      if (sd->style & Bold) { pr.style[i].font |= 1; }
      pr.style[i].fore[0] = '\0';
      if (sd->fg[0]) {
        getPDFRGB(pr.style[i].fore, sd->fg);
      } else if (i == STYLE_DEFAULT) {
        strcpy(pr.style[i].fore, "0 0 0 ");
      }
      pr.fontSize = PDF_FONTSIZE_DEFAULT;
    }
    // patch in default foregrounds
    for (int j = 0; j <= STYLE_MAX; j++) {
      if (pr.style[j].fore[0] == '\0') {
        strcpy(pr.style[j].fore, pr.style[STYLE_DEFAULT].fore);
      }
    }
  } else {
    for (int i = 0; i <= STYLE_MAX; i++) {
      strcpy(pr.style[i].fore, "0 0 0 ");
    }
  }


  // initialise PDF rendering
  PDFObjectTracker ot(fp);
  pr.oT = &ot;
  pr.startPDF();

  // do here all the writing
  int lengthDoc = sci->GetTextLength();
  int lineIndex = 0;

  if (!lengthDoc) {  // enable zero length docs
    pr.nextLine();
  } else {
    FX88591Codec *codec = sci->GetUTF8() ? new FX88591Codec() : NULL;
    for (int i = 0; i < lengthDoc; i++) {
      char ch = sci->sendMessage(SCI_GETCHARAT,i,0);
      int style = sci->sendMessage(SCI_GETSTYLEAT,i,0);

      if (ch == '\t') {
        // expand tabs
        int ts = tabSize - (lineIndex % tabSize);
        lineIndex += ts;
        for (; ts; ts--) {  // add ts count of spaces
          pr.add(' ', style);  // add spaces
        }
      } else if (ch == '\r' || ch == '\n') {
        if (ch == '\r' && sci->sendMessage(SCI_GETCHARAT,i+1,0) == '\n') {
          i++;
        }
        // close and begin a newline...
        pr.nextLine();
        lineIndex = 0;
      } else {
        // write the character normally...
        if (codec) {
          long charlen=sci->sendMessage(SCI_POSITIONAFTER,i,0)-i;
          if ((charlen>1)&&(charlen<=8)) {
            // PDF doesn't like UTF-8, try conversion to single-byte ISO-8859
            char utf[9]="\0";
            char asc[2]="\0";
            Sci_TextRange tr;
            tr.chrg.cpMin=i;
            tr.chrg.cpMax=i+charlen;
            tr.lpstrText=utf;
            sci->sendMessage(SCI_GETTEXTRANGE, 0, reinterpret_cast<long>(&tr));
            codec->utf2mb(asc, sizeof(asc), tr.lpstrText, charlen);
            if (asc[0]&&!asc[1]) {
              // Conversion succeeded: use our single byte and move past the multi-bytes
              ch=asc[0];
              i+=charlen-1;
            }
          }
        }
        pr.add(ch, style);
        lineIndex++;
      }
    }
    if (codec) { delete codec; }
  }

  // write required stuff and close the PDF file
  pr.endPDF();

}
Exemplo n.º 4
0
// Somebody wants our selection; the text field will furnish it if the target doesn't
long TextLabel::onSelectionRequest(FXObject* sender,FXSelector sel,void* ptr)
{
    FXEvent *event=(FXEvent*)ptr;
    FXString string;
    FXuint   start;
    FXuint   len;

    // Make sure
    FXASSERT(0<=anchor && anchor<=contents.length());
    FXASSERT(0<=cursor && cursor<=contents.length());

    // Perhaps the target wants to supply its own data for the selection
    if (FXFrame::onSelectionRequest(sender,sel,ptr))
    	return 1;

    // Recognize the request?
    if (event->target==stringType || event->target==textType || event->target==utf8Type || event->target==utf16Type)
    {

        // Figure selected bytes
        if (anchor<cursor)
        {
            start=anchor;
            len=cursor-anchor;
        }
        else
        {
            start=cursor;
            len=anchor-cursor;
        }

        // Get selected fragment
        string=contents.mid(start,len);

        // If password mode, replace by stars
        if (options&TEXTFIELD_PASSWD)
        	string.assign('*',string.count());

        // Return text of the selection as UTF-8
        if (event->target==utf8Type)
        {
            setDNDData(FROM_SELECTION,event->target,string);
            return 1;
        }

        // Return text of the selection translated to 8859-1
        if (event->target==stringType || event->target==textType)
        {
            FX88591Codec ascii;
            setDNDData(FROM_SELECTION,event->target,ascii.utf2mb(string));
            return 1;
        }

        // Return text of the selection translated to UTF-16
        if (event->target==utf16Type)
        {
            FXUTF16LECodec unicode;           // FIXME maybe other endianness for unix
            setDNDData(FROM_SELECTION,event->target,unicode.utf2mb(string));
            return 1;
        }
    }
    return 0;
}