1 19 20 package jxl.write.biff; 21 22 import java.net.URL ; 23 import java.net.MalformedURLException ; 24 import java.io.File ; 25 import java.util.ArrayList ; 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 48 public class HyperlinkRecord extends WritableRecordData 49 { 50 53 private static Logger logger = Logger.getLogger(HyperlinkRecord.class); 54 55 58 private int firstRow; 59 62 private int lastRow; 63 66 private int firstColumn; 67 70 private int lastColumn; 71 72 75 private URL url; 76 77 80 private File file; 81 82 85 private String location; 86 87 90 private String contents; 91 92 95 private LinkType linkType; 96 97 100 private byte[] data; 101 102 106 private Range range; 107 108 111 private WritableSheet sheet; 112 113 116 private boolean modified; 117 118 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 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 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 185 protected HyperlinkRecord(int col, int row, 186 int lastcol, int lastrow, 187 URL url, 188 String 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 216 protected HyperlinkRecord(int col, int row, int lastcol, int lastrow, 217 File file, String 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 256 protected HyperlinkRecord(int col, int row, 257 int lastcol, int lastrow, 258 String 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 284 public boolean isFile() 285 { 286 return linkType == fileLink; 287 } 288 289 294 public boolean isUNC() 295 { 296 return linkType == uncLink; 297 } 298 299 304 public boolean isURL() 305 { 306 return linkType == urlLink; 307 } 308 309 314 public boolean isLocation() 315 { 316 return linkType == workbookLink; 317 } 318 319 324 public int getRow() 325 { 326 return firstRow; 327 } 328 329 334 public int getColumn() 335 { 336 return firstColumn; 337 } 338 339 344 public int getLastRow() 345 { 346 return lastRow; 347 } 348 349 354 public int getLastColumn() 355 { 356 return lastColumn; 357 } 358 359 364 public URL getURL() 365 { 366 return url; 367 } 368 369 374 public File getFile() 375 { 376 return file; 377 } 378 379 384 public byte[] getData() 385 { 386 if (!modified) 387 { 388 return data; 389 } 390 391 byte[] commonData = new byte[32]; 393 394 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 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 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 479 public String 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 507 public Range getRange() 508 { 509 return range; 510 } 511 512 517 public void setURL(URL 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 return; 530 } 531 532 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 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 return; 559 } 560 561 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 580 protected void setLocation(String 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 return; 597 } 598 599 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 617 private void setLocation(WritableSheet sheet, 618 int destcol, int destrow, 619 int lastdestcol, int lastdestrow) 620 { 621 StringBuffer sb = new StringBuffer (); 622 sb.append('\''); 623 624 if (sheet.getName().indexOf('\'') == -1) 625 { 626 sb.append(sheet.getName()); 627 } 628 else 629 { 630 632 String 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 666 void insertRow(int r) 667 { 668 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 702 void insertColumn(int c) 703 { 704 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 738 void removeRow(int r) 739 { 740 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 775 void removeColumn(int c) 776 { 777 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 813 private byte[] getURLData(byte[] cd) 814 { 815 String 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 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 IntegerHelper.getFourBytes((urlString.length() + 1)*2, d, urlPos+16); 857 858 StringHelper.getUnicodeBytes(urlString, d, urlPos+20); 860 861 return d; 862 } 863 864 870 private byte[] getUNCData(byte[] cd) 871 { 872 String 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 int length = uncString.length() + 1; 881 IntegerHelper.getFourBytes(length, d, urlPos); 882 883 StringHelper.getUnicodeBytes(uncString, d, urlPos + 4); 885 886 return d; 887 } 888 889 895 private byte[] getFileData(byte[] cd) 896 { 897 ArrayList path = new ArrayList (); 899 ArrayList shortFileName = new ArrayList (); 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 int upLevelCount = 0; 914 int pos = path.size() - 1; 915 boolean upDir = true; 916 917 while (upDir) 918 { 919 String s = (String ) 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 filePathSB = new StringBuffer (); 935 StringBuffer shortFilePathSB = new StringBuffer (); 936 937 for (int i = path.size() - 1; i >= 0 ; i--) 938 { 939 filePathSB.append((String )path.get(i)); 940 shortFilePathSB.append((String )shortFileName.get(i)); 941 942 if (i != 0) 943 { 944 filePathSB.append("\\"); 945 shortFilePathSB.append("\\"); 946 } 947 } 948 949 String filePath = filePathSB.toString(); 950 String 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 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 IntegerHelper.getTwoBytes(upLevelCount, d, filePos+16); 993 994 IntegerHelper.getFourBytes((shortFilePath.length() + 1)*2, d, filePos+18); 996 997 StringHelper.getUnicodeBytes(shortFilePath, d, filePos+22); 999 1000 int curPos=filePos+22+(shortFilePath.length() + 1)*2; 1001 1002 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 IntegerHelper.getFourBytes(nameLength+6, d, curPos); 1013 1014 IntegerHelper.getFourBytes(nameLength, d, curPos+4); 1016 1017 d[curPos+8] = 0x03; 1019 1020 StringHelper.getUnicodeBytes(filePath, d, curPos+10); 1022 1023 return d; 1024 } 1025 1026 1032 private String getShortName(String s) 1033 { 1034 int sep = s.indexOf('.'); 1035 1036 String prefix = null; 1037 String 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 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 IntegerHelper.getFourBytes(location.length() + 1, d, locPos); 1083 1084 StringHelper.getUnicodeBytes(location, d, locPos+4); 1086 1087 return d; 1088 } 1089 1090 1091 1096 void initialize(WritableSheet s) 1097 { 1098 sheet = s; 1099 range = new SheetRangeImpl(s, 1100 firstColumn, firstRow, 1101 lastColumn, lastRow); 1102 } 1103 1104 1110 String getContents() 1111 { 1112 return contents; 1113 } 1114 1115 1120 protected void setContents(String desc) 1121 { 1122 contents = desc; 1123 modified = true; 1124 } 1125} 1126 1127 1128 1129 1130 1131 1132 1133 | Popular Tags |