KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > write > biff > HyperlinkRecord


1 /*********************************************************************
2 *
3 * Copyright (C) 2002 Andrew Khan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ***************************************************************************/

19
20 package jxl.write.biff;
21
22 import java.net.URL JavaDoc;
23 import java.net.MalformedURLException JavaDoc;
24 import java.io.File JavaDoc;
25 import java.util.ArrayList JavaDoc;
26
27 import common.Assert;
28 import common.Logger;
29
30 import jxl.CellType;
31 import jxl.Range;
32 import jxl.Hyperlink;
33 import jxl.write.WritableSheet;
34 import jxl.write.WritableCell;
35 import jxl.write.WritableHyperlink;
36 import jxl.write.Label;
37 import jxl.biff.IntegerHelper;
38 import jxl.biff.StringHelper;
39 import jxl.biff.CellReferenceHelper;
40 import jxl.biff.WritableRecordData;
41 import jxl.biff.Type;
42 import jxl.biff.SheetRangeImpl;
43
44 /**
45  * A number record. This is stored as 8 bytes, as opposed to the
46  * 4 byte RK record
47  */

48 public class HyperlinkRecord extends WritableRecordData
49 {
50   /**
51    * The logger
52    */

53   private static Logger logger = Logger.getLogger(HyperlinkRecord.class);
54
55   /**
56    * The first row
57    */

58   private int firstRow;
59   /**
60    * The last row
61    */

62   private int lastRow;
63   /**
64    * The first column
65    */

66   private int firstColumn;
67   /**
68    * The last column
69    */

70   private int lastColumn;
71
72   /**
73    * The URL referred to by this hyperlink
74    */

75   private URL JavaDoc url;
76
77   /**
78    * The local file referred to by this hyperlink
79    */

80   private File file;
81
82   /**
83    * The location in this workbook referred to by this hyperlink
84    */

85   private String JavaDoc location;
86
87   /**
88    * The cell contents of the cell which activate this hyperlink
89    */

90   private String JavaDoc contents;
91
92   /**
93    * The type of this hyperlink
94    */

95   private LinkType linkType;
96
97   /**
98    * The data for this hyperlink
99    */

100   private byte[] data;
101
102   /**
103    * The range of this hyperlink. When creating a hyperlink, this will
104    * be null until the hyperlink is added to the sheet
105    */

106   private Range range;
107
108   /**
109    * The sheet containing this hyperlink
110    */

111   private WritableSheet sheet;
112
113   /**
114    * Indicates whether this record has been modified since it was copied
115    */

116   private boolean modified;
117
118   /**
119    * The excel type of hyperlink
120    */

121   private static class LinkType {};
122
123   private static final LinkType urlLink = new LinkType();
124   private static final LinkType fileLink = new LinkType();
125   private static final LinkType uncLink = new LinkType();
126   private static final LinkType workbookLink = new LinkType();
127   private static final LinkType unknown = new LinkType();
128
129   /**
130    * Constructs this object from the readable spreadsheet
131    *
132    * @param hl the hyperlink from the read spreadsheet
133    */

134   protected HyperlinkRecord(Hyperlink h, WritableSheet s)
135   {
136     super(Type.HLINK);
137
138     Assert.verify(h instanceof jxl.read.biff.HyperlinkRecord);
139
140     jxl.read.biff.HyperlinkRecord hl = (jxl.read.biff.HyperlinkRecord) h;
141
142     data = hl.getRecord().getData();
143     sheet = s;
144
145     // Populate this hyperlink with the copied data
146
firstRow = hl.getRow();
147     firstColumn = hl.getColumn();
148     lastRow = hl.getLastRow();
149     lastColumn = hl.getLastColumn();
150     range = new SheetRangeImpl(s,
151                                      firstColumn, firstRow,
152                                      lastColumn, lastRow);
153
154     linkType = unknown;
155
156     if (hl.isFile())
157     {
158       linkType = fileLink;
159       file = hl.getFile();
160     }
161     else if (hl.isURL())
162     {
163       linkType = urlLink;
164       url = hl.getURL();
165     }
166     else if (hl.isLocation())
167     {
168       linkType = workbookLink;
169       location = hl.getLocation();
170     }
171
172     modified = false;
173   }
174
175   /**
176    * Constructs a URL hyperlink to a range of cells
177    *
178    * @param col the column containing this hyperlink
179    * @param row the row containing this hyperlink
180    * @param lastcol the last column which activates this hyperlink
181    * @param lastrow the last row which activates this hyperlink
182    * @param url the hyperlink
183    * @param desc the description
184    */

185   protected HyperlinkRecord(int col, int row,
186                             int lastcol, int lastrow,
187                             URL JavaDoc url,
188                             String JavaDoc desc)
189   {
190     super(Type.HLINK);
191
192     firstColumn = col;
193     firstRow = row;
194
195     lastColumn = Math.max(firstColumn, lastcol);
196     lastRow = Math.max(firstRow, lastrow);
197     
198     this.url = url;
199     contents = desc;
200
201     linkType = urlLink;
202
203     modified = true;
204   }
205
206   /**
207    * Constructs a File hyperlink to a range of cells
208    *
209    * @param col the column containing this hyperlink
210    * @param row the row containing this hyperlink
211    * @param lastcol the last column which activates this hyperlink
212    * @param lastrow the last row which activates this hyperlink
213    * @param file the hyperlink
214    * @param desc the description
215    */

216   protected HyperlinkRecord(int col, int row, int lastcol, int lastrow,
217                             File file, String JavaDoc desc)
218   {
219     super(Type.HLINK);
220
221     firstColumn = col;
222     firstRow = row;
223
224     lastColumn = Math.max(firstColumn, lastcol);
225     lastRow = Math.max(firstRow, lastrow);
226     contents = desc;
227     
228     this.file = file;
229
230     if (file.getPath().startsWith("\\\\"))
231     {
232       linkType = uncLink;
233     }
234     else
235     {
236       linkType = fileLink;
237     }
238
239     modified = true;
240   }
241
242   /**
243    * Constructs a hyperlink to some cells within this workbook
244    *
245    * @param col the column containing this hyperlink
246    * @param row the row containing this hyperlink
247    * @param lastcol the last column which activates this hyperlink
248    * @param lastrow the last row which activates this hyperlink
249    * @param desc the contents of the cell which describe this hyperlink
250    * @param sheet the sheet containing the cells to be linked to
251    * @param destcol the column number of the first destination linked cell
252    * @param destrow the row number of the first destination linked cell
253    * @param lastdestcol the column number of the last destination linked cell
254    * @param lastdestrow the row number of the last destination linked cell
255    */

256   protected HyperlinkRecord(int col, int row,
257                             int lastcol, int lastrow,
258                             String JavaDoc desc,
259                             WritableSheet s,
260                             int destcol, int destrow,
261                             int lastdestcol, int lastdestrow)
262   {
263     super(Type.HLINK);
264
265     firstColumn = col;
266     firstRow = row;
267
268     lastColumn = Math.max(firstColumn, lastcol);
269     lastRow = Math.max(firstRow, lastrow);
270     
271     setLocation(s, destcol, destrow, lastdestcol, lastdestrow);
272     contents = desc;
273
274     linkType = workbookLink;
275
276     modified = true;
277   }
278
279   /**
280    * Determines whether this is a hyperlink to a file
281    *
282    * @return TRUE if this is a hyperlink to a file, FALSE otherwise
283    */

284   public boolean isFile()
285   {
286     return linkType == fileLink;
287   }
288
289   /**
290    * Determines whether this is a hyperlink to a UNC
291    *
292    * @return TRUE if this is a hyperlink to a UNC, FALSE otherwise
293    */

294   public boolean isUNC()
295   {
296     return linkType == uncLink;
297   }
298
299   /**
300    * Determines whether this is a hyperlink to a web resource
301    *
302    * @return TRUE if this is a URL
303    */

304   public boolean isURL()
305   {
306     return linkType == urlLink;
307   }
308
309   /**
310    * Determines whether this is a hyperlink to a location in this workbook
311    *
312    * @return TRUE if this is a link to an internal location
313    */

314   public boolean isLocation()
315   {
316     return linkType == workbookLink;
317   }
318
319   /**
320    * Returns the row number of the top left cell
321    *
322    * @return the row number of this cell
323    */

324   public int getRow()
325   {
326     return firstRow;
327   }
328
329   /**
330    * Returns the column number of the top left cell
331    *
332    * @return the column number of this cell
333    */

334   public int getColumn()
335   {
336     return firstColumn;
337   }
338
339   /**
340    * Returns the row number of the bottom right cell
341    *
342    * @return the row number of this cell
343    */

344   public int getLastRow()
345   {
346     return lastRow;
347   }
348
349   /**
350    * Returns the column number of the bottom right cell
351    *
352    * @return the column number of this cell
353    */

354   public int getLastColumn()
355   {
356     return lastColumn;
357   }
358
359   /**
360    * Gets the URL referenced by this Hyperlink
361    *
362    * @return the URL, or NULL if this hyperlink is not a URL
363    */

364   public URL JavaDoc getURL()
365   {
366     return url;
367   }
368
369   /**
370    * Returns the local file eferenced by this Hyperlink
371    *
372    * @return the file, or NULL if this hyperlink is not a file
373    */

374   public File getFile()
375   {
376     return file;
377   }
378
379   /**
380    * Gets the binary data to be written to the output file
381    *
382    * @return the data to write to file
383    */

384   public byte[] getData()
385   {
386     if (!modified)
387     {
388       return data;
389     }
390
391     // Build up the common data
392
byte[] commonData = new byte[32];
393
394     // Set the range of cells this hyperlink applies to
395
IntegerHelper.getTwoBytes(firstRow, commonData, 0);
396     IntegerHelper.getTwoBytes(lastRow, commonData, 2);
397     IntegerHelper.getTwoBytes(firstColumn, commonData, 4);
398     IntegerHelper.getTwoBytes(lastColumn, commonData, 6);
399
400     // Some inexplicable byte sequence
401
commonData[8] = (byte) 0xd0;
402     commonData[9] = (byte) 0xc9;
403     commonData[10] = (byte) 0xea;
404     commonData[11] = (byte) 0x79;
405     commonData[12] = (byte) 0xf9;
406     commonData[13] = (byte) 0xba;
407     commonData[14] = (byte) 0xce;
408     commonData[15] = (byte) 0x11;
409     commonData[16] = (byte) 0x8c;
410     commonData[17] = (byte) 0x82;
411     commonData[18] = (byte) 0x0;
412     commonData[19] = (byte) 0xaa;
413     commonData[20] = (byte) 0x0;
414     commonData[21] = (byte) 0x4b;
415     commonData[22] = (byte) 0xa9;
416     commonData[23] = (byte) 0x0b;
417     commonData[24] = (byte) 0x2;
418     commonData[25] = (byte) 0x0;
419     commonData[26] = (byte) 0x0;
420     commonData[27] = (byte) 0x0;
421
422     // Set up the option flags to indicate the type of this URL. There
423
// is no description
424
int optionFlags = 0;
425     if (isURL())
426     {
427       optionFlags = 3;
428       
429       if (contents != null)
430       {
431         optionFlags |= 0x14;
432       }
433     }
434     else if (isFile())
435     {
436       optionFlags = 1;
437
438       if (contents != null)
439       {
440         optionFlags |= 0x14;
441       }
442     }
443     else if (isLocation())
444     {
445       optionFlags = 8;
446     }
447     else if (isUNC())
448     {
449       optionFlags = 259;
450     }
451
452     IntegerHelper.getFourBytes(optionFlags, commonData, 28);
453
454     if (isURL())
455     {
456       data = getURLData(commonData);
457     }
458     else if (isFile())
459     {
460       data = getFileData(commonData);
461     }
462     else if (isLocation())
463     {
464       data = getLocationData(commonData);
465     }
466     else if (isUNC())
467     {
468       data = getUNCData(commonData);
469     }
470
471     return data;
472   }
473
474   /**
475    * A standard toString method
476    *
477    * @return the contents of this object as a string
478    */

479   public String JavaDoc toString()
480   {
481     if (isFile())
482     {
483       return file.toString();
484     }
485     else if (isURL())
486     {
487       return url.toString();
488     }
489     else if (isUNC())
490     {
491       return file.toString();
492     }
493     else
494     {
495       return "";
496     }
497   }
498
499   /**
500    * Gets the range of cells which activate this hyperlink
501    * The get sheet index methods will all return -1, because the
502    * cells will all be present on the same sheet
503    *
504    * @return the range of cells which activate the hyperlink or NULL
505    * if this hyperlink has not been added to the sheet
506    */

507   public Range getRange()
508   {
509     return range;
510   }
511
512   /**
513    * Sets the URL of this hyperlink
514    *
515    * @param url the url
516    */

517   public void setURL(URL JavaDoc url)
518   {
519     linkType = urlLink;
520     file = null;
521     location = null;
522     contents = null;
523     this.url = url;
524     modified = true;
525
526     if (sheet == null)
527     {
528       // hyperlink has not been added to the sheet yet, so simply return
529
return;
530     }
531
532     // Change the label on the sheet
533
WritableCell wc = sheet.getWritableCell(firstColumn, firstRow);
534     
535     Assert.verify(wc.getType() == CellType.LABEL);
536
537     Label l = (Label) wc;
538     l.setString(url.toString());
539   }
540
541   /**
542    * Sets the file activated by this hyperlink
543    *
544    * @param file the file
545    */

546   public void setFile(File file)
547   {
548     linkType = fileLink;
549     url = null;
550     location = null;
551     contents = null;
552     this.file = file;
553     modified = true;
554
555     if (sheet == null)
556     {
557       // hyperlink has not been added to the sheet yet, so simply return
558
return;
559     }
560
561     // Change the label on the sheet
562
WritableCell wc = sheet.getWritableCell(firstColumn, firstRow);
563     
564     Assert.verify(wc.getType() == CellType.LABEL);
565
566     Label l = (Label) wc;
567     l.setString(file.toString());
568   }
569
570   /**
571    * Sets the location of the cells to be linked to within this workbook
572    *
573    * @param desc the label describing the link
574    * @param sheet the sheet containing the cells to be linked to
575    * @param destcol the column number of the first destination linked cell
576    * @param destrow the row number of the first destination linked cell
577    * @param lastdestcol the column number of the last destination linked cell
578    * @param lastdestrow the row number of the last destination linked cell
579    */

580   protected void setLocation(String JavaDoc desc,
581                              WritableSheet sheet,
582                              int destcol, int destrow,
583                              int lastdestcol, int lastdestrow)
584   {
585     linkType = workbookLink;
586     url = null;
587     file = null;
588     modified = true;
589     contents = desc;
590
591     setLocation(sheet, destcol, destrow, lastdestcol, lastdestrow);
592
593     if (sheet == null)
594     {
595       // hyperlink has not been added to the sheet yet, so simply return
596
return;
597     }
598
599     // Change the label on the sheet
600
WritableCell wc = sheet.getWritableCell(firstColumn, firstRow);
601     
602     Assert.verify(wc.getType() == CellType.LABEL);
603
604     Label l = (Label) wc;
605     l.setString(desc);
606   }
607
608   /**
609     * Initializes the location from the data passed in
610    *
611    * @param sheet the sheet containing the cells to be linked to
612    * @param destcol the column number of the first destination linked cell
613    * @param destrow the row number of the first destination linked cell
614    * @param lastdestcol the column number of the last destination linked cell
615    * @param lastdestrow the row number of the last destination linked cell
616    */

617   private void setLocation(WritableSheet sheet,
618                            int destcol, int destrow,
619                            int lastdestcol, int lastdestrow)
620   {
621     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
622     sb.append('\'');
623     
624     if (sheet.getName().indexOf('\'') == -1)
625     {
626       sb.append(sheet.getName());
627     }
628     else
629     {
630       // sb.append(sheet.getName().replaceAll("'", "''"));
631

632       // Can't use replaceAll as it is only 1.4 compatible, so have to
633
// do this the tedious way
634
String JavaDoc sheetName = sheet.getName();
635       int pos = 0 ;
636       int nextPos = sheetName.indexOf('\'', pos);
637
638       while (nextPos != -1 && pos < sheetName.length())
639       {
640         sb.append(sheetName.substring(pos, nextPos));
641         sb.append("''");
642         pos = nextPos + 1;
643         nextPos = sheetName.indexOf('\'', pos);
644       }
645       sb.append(sheetName.substring(pos));
646     }
647
648     sb.append('\'');
649     sb.append('!');
650     
651     lastdestcol = Math.max(destcol, lastdestcol);
652     lastdestrow = Math.max(destrow, lastdestrow);
653
654     CellReferenceHelper.getCellReference(destcol, destrow, sb);
655     sb.append(':');
656     CellReferenceHelper.getCellReference(lastdestcol, lastdestrow, sb);
657
658     location = sb.toString();
659   }
660
661   /**
662    * A row has been inserted, so adjust the range objects accordingly
663    *
664    * @param r the row which has been inserted
665    */

666   void insertRow(int r)
667   {
668     // This will not be called unless the hyperlink has been added to the
669
// sheet
670
Assert.verify(sheet != null && range != null);
671
672     if (r > lastRow)
673     {
674       return;
675     }
676
677     if (r <= firstRow)
678     {
679       firstRow++;
680       modified = true;
681     }
682
683     if (r <= lastRow)
684     {
685       lastRow++;
686       modified = true;
687     }
688
689     if (modified)
690     {
691       range = new SheetRangeImpl(sheet,
692                                   firstColumn, firstRow,
693                                   lastColumn, lastRow);
694     }
695   }
696
697   /**
698    * A column has been inserted, so adjust the range objects accordingly
699    *
700    * @param c the column which has been inserted
701    */

702   void insertColumn(int c)
703   {
704     // This will not be called unless the hyperlink has been added to the
705
// sheet
706
Assert.verify(sheet != null && range != null);
707
708     if (c > lastColumn)
709     {
710       return;
711     }
712
713     if (c <= firstColumn)
714     {
715       firstColumn++;
716       modified = true;
717     }
718
719     if (c <= lastColumn)
720     {
721       lastColumn++;
722       modified = true;
723     }
724
725     if (modified)
726     {
727       range = new SheetRangeImpl(sheet,
728                                   firstColumn, firstRow,
729                                   lastColumn, lastRow);
730     }
731   }
732
733   /**
734    * A row has been removed, so adjust the range objects accordingly
735    *
736    * @param r the row which has been inserted
737    */

738   void removeRow(int r)
739   {
740     // This will not be called unless the hyperlink has been added to the
741
// sheet
742
Assert.verify(sheet != null && range != null);
743
744     if (r > lastRow)
745     {
746       return;
747     }
748
749     if (r < firstRow)
750     {
751       firstRow--;
752       modified = true;
753     }
754
755     if (r < lastRow)
756     {
757       lastRow--;
758       modified = true;
759     }
760
761     if (modified)
762     {
763       Assert.verify(range != null);
764       range = new SheetRangeImpl(sheet,
765                                   firstColumn, firstRow,
766                                   lastColumn, lastRow);
767     }
768   }
769
770   /**
771    * A column has been removed, so adjust the range objects accordingly
772    *
773    * @param c the column which has been removed
774    */

775   void removeColumn(int c)
776   {
777     // This will not be called unless the hyperlink has been added to the
778
// sheet
779
Assert.verify(sheet != null && range != null);
780
781     if (c > lastColumn)
782     {
783       return;
784     }
785
786     if (c < firstColumn)
787     {
788       firstColumn--;
789       modified = true;
790     }
791
792     if (c < lastColumn)
793     {
794       lastColumn--;
795       modified = true;
796     }
797
798     if (modified)
799     {
800       Assert.verify(range != null);
801       range = new SheetRangeImpl(sheet,
802                                   firstColumn, firstRow,
803                                   lastColumn, lastRow);
804     }
805   }
806
807   /**
808    * Gets the hyperlink stream specific to a URL link
809    *
810    * @param cd the data common for all types of hyperlink
811    * @return the raw data for a URL hyperlink
812    */

813   private byte[] getURLData(byte[] cd)
814   {
815     String JavaDoc urlString = url.toString();
816
817     int dataLength = cd.length + 20 + (urlString.length() + 1)* 2;
818
819     if (contents != null)
820     {
821       dataLength += 4 + (contents.length() + 1) * 2;
822     }
823
824     byte[] d = new byte[dataLength];
825
826     System.arraycopy(cd, 0, d, 0, cd.length);
827     
828     int urlPos = cd.length;
829
830     if (contents != null)
831     {
832       IntegerHelper.getFourBytes(contents.length() + 1, d, urlPos);
833       StringHelper.getUnicodeBytes(contents, d, urlPos + 4);
834       urlPos += (contents.length() + 1) * 2 + 4;
835     }
836     
837     // Inexplicable byte sequence
838
d[urlPos] = (byte) 0xe0;
839     d[urlPos+1] = (byte) 0xc9;
840     d[urlPos+2] = (byte) 0xea;
841     d[urlPos+3] = (byte) 0x79;
842     d[urlPos+4] = (byte) 0xf9;
843     d[urlPos+5] = (byte) 0xba;
844     d[urlPos+6] = (byte) 0xce;
845     d[urlPos+7] = (byte) 0x11;
846     d[urlPos+8] = (byte) 0x8c;
847     d[urlPos+9] = (byte) 0x82;
848     d[urlPos+10] = (byte) 0x0;
849     d[urlPos+11] = (byte) 0xaa;
850     d[urlPos+12] = (byte) 0x0;
851     d[urlPos+13] = (byte) 0x4b;
852     d[urlPos+14] = (byte) 0xa9;
853     d[urlPos+15] = (byte) 0x0b;
854
855     // Number of characters in the url, including a zero trailing character
856
IntegerHelper.getFourBytes((urlString.length() + 1)*2, d, urlPos+16);
857
858     // Put the url into the data string
859
StringHelper.getUnicodeBytes(urlString, d, urlPos+20);
860     
861     return d;
862   }
863
864   /**
865    * Gets the hyperlink stream specific to a URL link
866    *
867    * @param cd the data common for all types of hyperlink
868    * @return the raw data for a URL hyperlink
869    */

870   private byte[] getUNCData(byte[] cd)
871   {
872     String JavaDoc uncString = file.getPath();
873
874     byte[] d = new byte[cd.length + uncString.length() * 2 + 2 + 4];
875     System.arraycopy(cd, 0, d, 0, cd.length);
876
877     int urlPos = cd.length;
878     
879     // The length of the unc string, including zero terminator
880
int length = uncString.length() + 1;
881     IntegerHelper.getFourBytes(length, d, urlPos);
882
883     // Place the string into the stream
884
StringHelper.getUnicodeBytes(uncString, d, urlPos + 4);
885
886     return d;
887   }
888
889   /**
890    * Gets the hyperlink stream specific to a local file link
891    *
892    * @param cd the data common for all types of hyperlink
893    * @return the raw data for a URL hyperlink
894    */

895   private byte[] getFileData(byte[] cd)
896   {
897     // Build up the directory hierarchy in reverse order
898
ArrayList JavaDoc path = new ArrayList JavaDoc();
899     ArrayList JavaDoc shortFileName = new ArrayList JavaDoc();
900     path.add(file.getName());
901     shortFileName.add(getShortName(file.getName()));
902
903     File parent = file.getParentFile();
904     while (parent != null)
905     {
906       path.add(parent.getName());
907       shortFileName.add(getShortName(parent.getName()));
908       parent = parent.getParentFile();
909     }
910
911     // Deduce the up directory level count and remove the directory from
912
// the path
913
int upLevelCount = 0;
914     int pos = path.size() - 1;
915     boolean upDir = true;
916
917     while (upDir)
918     {
919       String JavaDoc s = (String JavaDoc) path.get(pos);
920       if (s.equals(".."))
921       {
922         upLevelCount++;
923         path.remove(pos);
924         shortFileName.remove(pos);
925       }
926       else
927       {
928         upDir = false;
929       }
930
931       pos--;
932     }
933
934     StringBuffer JavaDoc filePathSB = new StringBuffer JavaDoc();
935     StringBuffer JavaDoc shortFilePathSB = new StringBuffer JavaDoc();
936
937     for (int i = path.size() - 1; i >= 0 ; i--)
938     {
939       filePathSB.append((String JavaDoc)path.get(i));
940       shortFilePathSB.append((String JavaDoc)shortFileName.get(i));
941
942       if (i != 0)
943       {
944         filePathSB.append("\\");
945         shortFilePathSB.append("\\");
946       }
947     }
948
949     String JavaDoc filePath = filePathSB.toString();
950     String JavaDoc shortFilePath = shortFilePathSB.toString();
951
952     int dataLength = cd.length + 22 + (shortFilePath.length() + 1) * 2 +
953                    34 + filePath.length() * 2;
954
955     if (contents != null)
956     {
957       dataLength += 4 + (contents.length() + 1) * 2;
958     }
959
960     byte[] d = new byte[dataLength];
961
962     System.arraycopy(cd, 0, d, 0, cd.length);
963     
964     int filePos = cd.length;
965
966     if (contents != null)
967     {
968       IntegerHelper.getFourBytes(contents.length() + 1, d, filePos);
969       StringHelper.getUnicodeBytes(contents, d, filePos + 4);
970       filePos += (contents.length() + 1) * 2 + 4;
971     }
972
973     // Inexplicable byte sequence
974
d[filePos] = (byte) 0x03;
975     d[filePos+1] = (byte) 0x03;
976     d[filePos+2] = (byte) 0x0;
977     d[filePos+3] = (byte) 0x0;
978     d[filePos+4] = (byte) 0x0;
979     d[filePos+5] = (byte) 0x0;
980     d[filePos+6] = (byte) 0x0;
981     d[filePos+7] = (byte) 0x0;
982     d[filePos+8] = (byte) 0xc0;
983     d[filePos+9] = (byte) 0x0;
984     d[filePos+10] = (byte) 0x0;
985     d[filePos+11] = (byte) 0x0;
986     d[filePos+12] = (byte) 0x0;
987     d[filePos+13] = (byte) 0x0;
988     d[filePos+14] = (byte) 0x0;
989     d[filePos+15] = (byte) 0x46;
990
991     // The directory up level count
992
IntegerHelper.getTwoBytes(upLevelCount, d, filePos+16);
993
994     // The number of bytes in the short file name, including zero terminator
995
IntegerHelper.getFourBytes((shortFilePath.length() + 1)*2, d, filePos+18);
996
997     // The short file name
998
StringHelper.getUnicodeBytes(shortFilePath, d, filePos+22);
999
1000    int curPos=filePos+22+(shortFilePath.length() + 1)*2;
1001    
1002    // Inexplicable byte sequence
1003
d[curPos] = (byte) 0xff;
1004    d[curPos+1] = (byte) 0xff;
1005    d[curPos+2] = (byte) 0xad;
1006    d[curPos+3] = (byte) 0xde;
1007
1008    curPos += 24;
1009    int nameLength = filePath.length() * 2;
1010
1011    // Size of the file link
1012
IntegerHelper.getFourBytes(nameLength+6, d, curPos);
1013
1014    // Number of characters
1015
IntegerHelper.getFourBytes(nameLength, d, curPos+4);
1016
1017    // Inexplicable byte sequence
1018
d[curPos+8] = 0x03;
1019    
1020    // The long file name
1021
StringHelper.getUnicodeBytes(filePath, d, curPos+10);
1022
1023    return d;
1024  }
1025
1026  /**
1027   * Gets the DOS short file name in 8.3 format of the name passed in
1028   *
1029   * @param s the name
1030   * @return the dos short name
1031   */

1032  private String JavaDoc getShortName(String JavaDoc s)
1033  {
1034    int sep = s.indexOf('.');
1035    
1036    String JavaDoc prefix = null;
1037    String JavaDoc suffix = null;
1038
1039    if (sep == -1)
1040    {
1041      prefix = s;
1042      suffix="";
1043    }
1044    else
1045    {
1046      prefix = s.substring(0,sep);
1047      suffix = s.substring(sep+1);
1048    }
1049
1050    if (prefix.length() > 8)
1051    {
1052      prefix = prefix.substring(0, 6) + "~" + (prefix.length() - 6);
1053      prefix = prefix.substring(0, 8);
1054    }
1055
1056    suffix = suffix.substring(0,Math.min(3, suffix.length()));
1057
1058    if (suffix.length() > 0)
1059    {
1060      return prefix + '.' + suffix;
1061    }
1062    else
1063    {
1064      return prefix;
1065    }
1066  }
1067
1068  /**
1069   * Gets the hyperlink stream specific to a location link
1070   *
1071   * @param cd the data common for all types of hyperlink
1072   * @return the raw data for a URL hyperlink
1073   */

1074  private byte[] getLocationData(byte[] cd)
1075  {
1076    byte[] d = new byte[cd.length + 4 + (location.length() + 1)* 2];
1077    System.arraycopy(cd, 0, d, 0, cd.length);
1078
1079    int locPos = cd.length;
1080    
1081    // The number of chars in the location string, plus a 0 terminator
1082
IntegerHelper.getFourBytes(location.length() + 1, d, locPos);
1083    
1084    // Get the location
1085
StringHelper.getUnicodeBytes(location, d, locPos+4);
1086
1087    return d;
1088  }
1089
1090  
1091  /**
1092   * Initializes the range when this hyperlink is added to the sheet
1093   *
1094   * @param s the sheet containing this hyperlink
1095   */

1096  void initialize(WritableSheet s)
1097  {
1098    sheet = s;
1099    range = new SheetRangeImpl(s,
1100                               firstColumn, firstRow,
1101                               lastColumn, lastRow);
1102  }
1103
1104  /**
1105   * Called by the worksheet. Gets the string contents to put into the cell
1106   * containing this hyperlink
1107   *
1108   * @return the string contents for the hyperlink cell
1109   */

1110  String JavaDoc getContents()
1111  {
1112    return contents;
1113  }
1114
1115  /**
1116   * Sets the description
1117   *
1118   * @param desc the description
1119   */

1120  protected void setContents(String JavaDoc desc)
1121  {
1122    contents = desc;
1123    modified = true;
1124  }
1125}
1126
1127
1128
1129
1130
1131
1132
1133
Popular Tags