mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	Merge pull request #143 from abevoelker/improve-cls-detection
Improve .cls language detection
This commit is contained in:
		| @@ -423,8 +423,15 @@ module Linguist | |||||||
|     def guess_cls_language |     def guess_cls_language | ||||||
|       if lines.grep(/^(%|\\)/).any? |       if lines.grep(/^(%|\\)/).any? | ||||||
|         Language['TeX'] |         Language['TeX'] | ||||||
|       else |       elsif lines.grep(/^\s*(CLASS|METHOD|INTERFACE).*:\s*/i).any? || lines.grep(/^\s*(USING|DEFINE)/i).any? | ||||||
|         Language['OpenEdge ABL'] |         Language['OpenEdge ABL'] | ||||||
|  |       elsif lines.grep(/\{$/).any? || lines.grep(/\}$/).any? | ||||||
|  |         Language['Apex'] | ||||||
|  |       elsif lines.grep(/^(\'\*|Attribute|Option|Sub|Private|Protected|Public|Friend)/i).any? | ||||||
|  |         Language['Visual Basic'] | ||||||
|  |       else | ||||||
|  |         # The most common language should be the fallback | ||||||
|  |         Language['TeX'] | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,6 +54,12 @@ Ada: | |||||||
|   - .adb |   - .adb | ||||||
|   - .ads |   - .ads | ||||||
|  |  | ||||||
|  | Apex: | ||||||
|  |   type: programming | ||||||
|  |   lexer: Text only | ||||||
|  |   extensions: | ||||||
|  |   - .cls | ||||||
|  |  | ||||||
| AppleScript: | AppleScript: | ||||||
|   aliases: |   aliases: | ||||||
|   - osascript |   - osascript | ||||||
| @@ -747,8 +753,6 @@ OpenEdge ABL: | |||||||
|   - openedge |   - openedge | ||||||
|   - abl |   - abl | ||||||
|   primary_extension: .p |   primary_extension: .p | ||||||
|   overrides: |  | ||||||
|   - .cls |  | ||||||
|   extensions: |   extensions: | ||||||
|   - .cls |   - .cls | ||||||
|   - .p |   - .p | ||||||
| @@ -1053,6 +1057,8 @@ Tcsh: | |||||||
| TeX: | TeX: | ||||||
|   type: markup |   type: markup | ||||||
|   primary_extension: .tex |   primary_extension: .tex | ||||||
|  |   overrides: | ||||||
|  |   - .cls | ||||||
|   extensions: |   extensions: | ||||||
|   - .aux |   - .aux | ||||||
|   - .cls |   - .cls | ||||||
|   | |||||||
							
								
								
									
										458
									
								
								test/fixtures/ArrayUtils.cls
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										458
									
								
								test/fixtures/ArrayUtils.cls
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,458 @@ | |||||||
|  | /* ============================================================ | ||||||
|  |  * This code is part of the "apex-lang" open source project avaiable at: | ||||||
|  |  *  | ||||||
|  |  *      http://code.google.com/p/apex-lang/ | ||||||
|  |  * | ||||||
|  |  * This code is licensed under the Apache License, Version 2.0.  You may obtain a  | ||||||
|  |  * copy of the License at: | ||||||
|  |  *  | ||||||
|  |  *      http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  |  * ============================================================ | ||||||
|  |  */ | ||||||
|  | global class ArrayUtils {    | ||||||
|  |      | ||||||
|  |     global static String[] EMPTY_STRING_ARRAY = new String[]{}; | ||||||
|  |     global static Integer MAX_NUMBER_OF_ELEMENTS_IN_LIST {get{return 1000;}} | ||||||
|  |      | ||||||
|  |     global static List<String> objectToString(List<Object> objects){ | ||||||
|  |         List<String> strings = null; | ||||||
|  |         if(objects != null){ | ||||||
|  |         	strings = new List<String>(); | ||||||
|  |         	if(objects.size() > 0){ | ||||||
|  | 	            for(Object obj : objects){ | ||||||
|  | 	                if(obj instanceof String){ | ||||||
|  | 	                    strings.add((String)obj); | ||||||
|  | 	                } | ||||||
|  | 	            } | ||||||
|  |         	} | ||||||
|  |         } | ||||||
|  |         return strings; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     global static Object[] reverse(Object[] anArray) { | ||||||
|  |         if (anArray == null) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         Integer i = 0; | ||||||
|  |         Integer j = anArray.size() - 1; | ||||||
|  |         Object tmp; | ||||||
|  |         while (j > i) { | ||||||
|  |             tmp = anArray[j]; | ||||||
|  |             anArray[j] = anArray[i]; | ||||||
|  |             anArray[i] = tmp; | ||||||
|  |             j--; | ||||||
|  |             i++; | ||||||
|  |         } | ||||||
|  |         return anArray; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static SObject[] reverse(SObject[] anArray) { | ||||||
|  |         if (anArray == null) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         Integer i = 0; | ||||||
|  |         Integer j = anArray.size() - 1; | ||||||
|  |         SObject tmp; | ||||||
|  |         while (j > i) { | ||||||
|  |             tmp = anArray[j]; | ||||||
|  |             anArray[j] = anArray[i]; | ||||||
|  |             anArray[i] = tmp; | ||||||
|  |             j--; | ||||||
|  |             i++; | ||||||
|  |         } | ||||||
|  |         return anArray; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static List<String> lowerCase(List<String> strs){ | ||||||
|  |         List<String> returnValue = null; | ||||||
|  |         if(strs != null){ | ||||||
|  |             returnValue = new List<String>(); | ||||||
|  |         	if(strs.size() > 0){ | ||||||
|  | 	            for(String str : strs){ | ||||||
|  | 	                returnValue.add(str == null ? null : str.toLowerCase()); | ||||||
|  | 	            } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnValue; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static List<String> upperCase(List<String> strs){ | ||||||
|  |         List<String> returnValue = null; | ||||||
|  |         if(strs != null){ | ||||||
|  |             returnValue = new List<String>(); | ||||||
|  |             if(strs.size() > 0){ | ||||||
|  | 	            for(String str : strs){ | ||||||
|  | 	                returnValue.add(str == null ? null : str.toUpperCase()); | ||||||
|  | 	            } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnValue; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static List<String> trim(List<String> strs){ | ||||||
|  |         List<String> returnValue = null; | ||||||
|  |         if(strs != null){ | ||||||
|  |             returnValue = new List<String>(); | ||||||
|  |             if(strs.size() > 0){ | ||||||
|  | 	            for(String str : strs){ | ||||||
|  | 	                returnValue.add(str == null ? null : str.trim()); | ||||||
|  | 	            } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnValue; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static Object[] mergex(Object[] array1, Object[] array2){ | ||||||
|  |         if(array1 == null){ return array2; } | ||||||
|  |         if(array2 == null){ return array1; } | ||||||
|  |         Object[] merged = new Object[array1.size() + array2.size()]; | ||||||
|  |         for(Integer i = 0; i < array1.size(); i++){ | ||||||
|  |             merged[i] = array1[i]; | ||||||
|  |         } | ||||||
|  |         for(Integer i = 0; i < array2.size(); i++){ | ||||||
|  |             merged[i+array1.size()] = array2[i]; | ||||||
|  |         } | ||||||
|  |         return merged; | ||||||
|  |     }    | ||||||
|  |       | ||||||
|  |     global static SObject[] mergex(SObject[] array1, SObject[] array2){ | ||||||
|  |         if(array1 == null){ return array2; } | ||||||
|  |         if(array2 == null){ return array1; } | ||||||
|  |         if(array1.size() <= 0){ return array2; } | ||||||
|  |         List<SObject> merged = new List<SObject>(); | ||||||
|  |         for(SObject sObj : array1){ merged.add(sObj); } | ||||||
|  |         for(SObject sObj : array2){ merged.add(sObj); } | ||||||
|  |         return merged; | ||||||
|  |     }    | ||||||
|  |      | ||||||
|  |     global static Boolean isEmpty(Object[] objectArray){ | ||||||
|  |         if(objectArray == null){ | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return objectArray.size() == 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static Boolean isEmpty(SObject[] objectArray){ | ||||||
|  |         if(objectArray == null){ | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return objectArray.size() == 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static Boolean isNotEmpty(Object[] objectArray){ | ||||||
|  |         return !isEmpty(objectArray); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static Boolean isNotEmpty(SObject[] objectArray){ | ||||||
|  |         return !isEmpty(objectArray); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static Object[] pluck(SObject[] objectArray, String fieldName){ | ||||||
|  |         if(isEmpty(objectArray) || fieldName == null || fieldName.trim() == null || fieldName.trim().length() == 0){ | ||||||
|  |             return new Object[]{}; | ||||||
|  |         } | ||||||
|  |         Object[] plucked = new Object[objectArray.size()]; | ||||||
|  |         for(Integer i = 0; i < objectArray.size(); i++){ | ||||||
|  |             plucked[i] = objectArray[i].get(fieldName); | ||||||
|  |         } | ||||||
|  |         return plucked; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     global static String toString(Object[] objectArray){ | ||||||
|  |         if(objectArray == null){ | ||||||
|  |             return 'null';     | ||||||
|  |         } | ||||||
|  |         String returnValue = '{'; | ||||||
|  |         for(Integer i = 0; i < objectArray.size(); i++){ | ||||||
|  |             if(i!=0){ returnValue += ','; } | ||||||
|  |             returnValue += '\'' + objectArray[i] + '\''; | ||||||
|  |         } | ||||||
|  |         returnValue += '}'; | ||||||
|  |         return returnValue;  | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static String toString(SObject[] objectArray){ | ||||||
|  |         if(objectArray == null){ | ||||||
|  |             return 'null';     | ||||||
|  |         } | ||||||
|  |         String returnValue = '{'; | ||||||
|  |         for(Integer i = 0; i < objectArray.size(); i++){ | ||||||
|  |             if(i!=0){ returnValue += ','; } | ||||||
|  |             returnValue += '\'' + objectArray[i] + '\''; | ||||||
|  |         } | ||||||
|  |         returnValue += '}'; | ||||||
|  |         return returnValue;  | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static void assertArraysAreEqual(Object[] expected, Object[] actual){ | ||||||
|  |         //check to see if one param is null but the other is not | ||||||
|  |         System.assert((expected == null && actual == null)|| (expected != null && actual != null), | ||||||
|  |             'Assertion failed, the following two arrays are not equal.  Expected: '  | ||||||
|  |                     + ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual)); | ||||||
|  |         if(expected != null && actual != null){ | ||||||
|  |             System.assert(expected.size() == actual.size(), 'Assertion failed, the following two arrays are not equal.  Expected: '  | ||||||
|  |                     + ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual)); | ||||||
|  |             for(Integer i = 0; i < expected.size(); i++){ | ||||||
|  |                 System.assert(expected[i] == actual[i], 'Assertion failed, the following two arrays are not equal.  Expected: '  | ||||||
|  |                     + ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static void assertArraysAreEqual(SObject[] expected, SObject[] actual){ | ||||||
|  |         //check to see if one param is null but the other is not | ||||||
|  |         System.assert((expected == null && actual == null)|| (expected != null && actual != null), | ||||||
|  |             'Assertion failed, the following two arrays are not equal.  Expected: '  | ||||||
|  |                     + ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual)); | ||||||
|  |         if(expected != null && actual != null){ | ||||||
|  |             System.assert(expected.size() == actual.size(), 'Assertion failed, the following two arrays are not equal.  Expected: '  | ||||||
|  |                     + ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual)); | ||||||
|  |             for(Integer i = 0; i < expected.size(); i++){ | ||||||
|  |                 System.assert(expected[i] == actual[i], 'Assertion failed, the following two arrays are not equal.  Expected: '  | ||||||
|  |                     + ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static List<Object> merg(List<Object> list1, List<Object> list2) { | ||||||
|  |         List<Object> returnList = new List<Object>(); | ||||||
|  |         if(list1 != null && list2 != null && (list1.size()+list2.size()) > MAX_NUMBER_OF_ELEMENTS_IN_LIST){ | ||||||
|  |             throw new IllegalArgumentException('Lists cannot be merged because new list would be greater than maximum number of elements in a list: ' + MAX_NUMBER_OF_ELEMENTS_IN_LIST); | ||||||
|  |         } | ||||||
|  |         if(isNotEmpty(list1)){ | ||||||
|  |             for(Object elmt : list1){ | ||||||
|  |                 returnList.add(elmt); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(isNotEmpty(list2)){ | ||||||
|  |             for(Object elmt : list2){ | ||||||
|  |                 returnList.add(elmt); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnList; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     global static List<SObject> merg(List<SObject> list1, List<SObject> list2) { | ||||||
|  |         if(list1 != null && list2 != null && (list1.size()+list2.size()) > MAX_NUMBER_OF_ELEMENTS_IN_LIST){ | ||||||
|  |             throw new IllegalArgumentException('Lists cannot be merged because new list would be greater than maximum number of elements in a list: ' + MAX_NUMBER_OF_ELEMENTS_IN_LIST); | ||||||
|  |         } | ||||||
|  |         if(isEmpty(list1) && isEmpty(list2)){ | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         List<SObject> returnList = new List<SObject>(); | ||||||
|  |         if(list1 != null){ | ||||||
|  |             for(SObject elmt : list1){ | ||||||
|  |                 returnList.add(elmt); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(list2 != null){ | ||||||
|  |             for(SObject elmt : list2){ | ||||||
|  |                 returnList.add(elmt); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnList; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static List<Object> subset(List<Object> aList, Integer count) { | ||||||
|  |         return subset(aList,0,count); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     global static List<Object> subset(List<Object> list1, Integer startIndex, Integer count) { | ||||||
|  |         List<Object> returnList = new List<Object>(); | ||||||
|  |         if(list1 != null && list1.size() > 0 && startIndex >= 0 && startIndex <= list1.size()-1 && count > 0){ | ||||||
|  |             for(Integer i = startIndex; i < list1.size() && i - startIndex < count; i++){ | ||||||
|  |                 returnList.add(list1.get(i)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnList; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     global static List<SObject> subset(List<SObject> aList, Integer count) { | ||||||
|  |         return subset(aList,0,count); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     global static List<SObject> subset(List<SObject> list1, Integer startIndex, Integer count) { | ||||||
|  |         List<SObject> returnList = null; | ||||||
|  |         if(list1 != null && list1.size() > 0 && startIndex <= list1.size()-1 && count > 0){ | ||||||
|  |             returnList = new List<SObject>(); | ||||||
|  |             for(Integer i = startIndex; i < list1.size() && i - startIndex < count; i++){ | ||||||
|  |                 returnList.add(list1.get(i)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return returnList; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     //=============================================== | ||||||
|  |     //LIST/ARRAY SORTING | ||||||
|  |     //=============================================== | ||||||
|  |  | ||||||
|  |     //FOR FORCE.COM PRIMITIVES (Double,Integer,ID,etc.): | ||||||
|  |     global static List<Object> qsort(List<Object> theList) { | ||||||
|  |         return qsort(theList,new PrimitiveComparator()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     global static List<Object> qsort(List<Object> theList, Boolean sortAsc) { | ||||||
|  |         return qsort(theList,new PrimitiveComparator(),sortAsc); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static List<Object> qsort(List<Object> theList, ObjectComparator comparator) { | ||||||
|  |         return qsort(theList,comparator,true); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static List<Object> qsort(List<Object> theList, ObjectComparator comparator, Boolean sortAsc) { | ||||||
|  |         return qsort(theList, 0, (theList == null ? 0 : theList.size()-1),comparator,sortAsc); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     //FOR SALESFORCE OBJECTS (sObjects): | ||||||
|  |     global static List<SObject> qsort(List<SObject> theList, ISObjectComparator comparator) { | ||||||
|  |         return qsort(theList,comparator,true); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     global static List<SObject> qsort(List<SObject> theList, ISObjectComparator comparator,Boolean sortAsc ) { | ||||||
|  |         return qsort(theList,  0, (theList == null ? 0 : theList.size()-1),comparator,sortAsc); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static List<Object> qsort(List<Object> theList, | ||||||
|  |                                 Integer lo0,  | ||||||
|  |                                 Integer hi0,  | ||||||
|  |                                 ObjectComparator comparator, | ||||||
|  |                                 Boolean sortAsc){ | ||||||
|  |         Integer lo = lo0; | ||||||
|  |         Integer hi = hi0; | ||||||
|  |       | ||||||
|  |         if (lo >= hi) { | ||||||
|  |             return theList; | ||||||
|  |         } else if( lo == hi - 1 ) { | ||||||
|  |          | ||||||
|  |             if (( comparator.compare(theList[lo],theList[hi])>0 && sortAsc) ||  | ||||||
|  |                   (comparator.compare(theList[lo],theList[hi])<0 && !sortAsc)     | ||||||
|  |                 ) { | ||||||
|  |                  Object prs = theList[lo]; | ||||||
|  |                  theList[lo]         = theList[hi]; | ||||||
|  |                  theList[hi]         = prs; | ||||||
|  |             } | ||||||
|  |             return theList; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Object pivot = theList[(lo + hi) / 2]; | ||||||
|  |         theList[(lo + hi) / 2] = theList[hi]; | ||||||
|  |         theList[hi] = pivot; | ||||||
|  |  | ||||||
|  |         while( lo < hi ) { | ||||||
|  |             while ((comparator.compare(theList[lo], pivot)<=0 && lo < hi && sortAsc) ||  | ||||||
|  |                    (comparator.compare(theList[lo], pivot)>=0 && lo < hi && !sortAsc) | ||||||
|  |                   ) { lo++; } | ||||||
|  |             while (( comparator.compare(pivot,theList[hi])<=0 && lo < hi && sortAsc) || | ||||||
|  |                    ( comparator.compare(pivot,theList[hi])>=0 && lo < hi && !sortAsc) | ||||||
|  |                   ) { hi--; } | ||||||
|  |              | ||||||
|  |             if( lo < hi ){ | ||||||
|  |                  Object prs = theList[lo]; | ||||||
|  |                  theList[lo]   = theList[hi]; | ||||||
|  |                  theList[hi]    = prs; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         theList[hi0] = theList[hi]; | ||||||
|  |         theList[hi] = pivot; | ||||||
|  |          | ||||||
|  |         qsort(theList, lo0, lo-1,comparator,sortAsc); | ||||||
|  |         qsort(theList, hi+1, hi0,comparator,sortAsc); | ||||||
|  |         return theList; | ||||||
|  |     }     | ||||||
|  |          | ||||||
|  |      | ||||||
|  |     private static List<SObject> qsort(List<SObject> theList, | ||||||
|  |                                 Integer lo0,  | ||||||
|  |                                 Integer hi0,  | ||||||
|  |                                 ISObjectComparator comparator, | ||||||
|  |                                 Boolean sortAsc){ | ||||||
|  |         Integer lo = lo0; | ||||||
|  |         Integer hi = hi0; | ||||||
|  |       | ||||||
|  |         if (lo >= hi) { | ||||||
|  |             return theList; | ||||||
|  |         } else if( lo == hi - 1 ) { | ||||||
|  |          | ||||||
|  |             if (( comparator.compare(theList[lo],theList[hi])>0 && sortAsc) ||  | ||||||
|  |                   (comparator.compare(theList[lo],theList[hi])<0 && !sortAsc)     | ||||||
|  |                 ) { | ||||||
|  |                  SObject prs = theList[lo]; | ||||||
|  |                  theList[lo]         = theList[hi]; | ||||||
|  |                  theList[hi]         = prs; | ||||||
|  |             } | ||||||
|  |             return theList; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         SObject pivot = theList[(lo + hi) / 2]; | ||||||
|  |         theList[(lo + hi) / 2] = theList[hi]; | ||||||
|  |         theList[hi] = pivot; | ||||||
|  |  | ||||||
|  |         while( lo < hi ) { | ||||||
|  |             while ((comparator.compare(theList[lo], pivot)<=0 && lo < hi && sortAsc) ||  | ||||||
|  |                    (comparator.compare(theList[lo], pivot)>=0 && lo < hi && !sortAsc) | ||||||
|  |                   ) { lo++; } | ||||||
|  |             while (( comparator.compare(pivot,theList[hi])<=0 && lo < hi && sortAsc) || | ||||||
|  |                    ( comparator.compare(pivot,theList[hi])>=0 && lo < hi && !sortAsc) | ||||||
|  |                   ) { hi--; } | ||||||
|  |              | ||||||
|  |             if( lo < hi ){ | ||||||
|  |                  SObject prs = theList[lo]; | ||||||
|  |                  theList[lo]   = theList[hi]; | ||||||
|  |                  theList[hi]    = prs; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         theList[hi0] = theList[hi]; | ||||||
|  |         theList[hi] = pivot; | ||||||
|  |          | ||||||
|  |         qsort(theList, lo0, lo-1,comparator,sortAsc); | ||||||
|  |         qsort(theList, hi+1, hi0,comparator,sortAsc); | ||||||
|  |         return theList; | ||||||
|  |     } | ||||||
|  | /* | ||||||
|  |     global static List<Object> unique(List<Object> theList) { | ||||||
|  |         List<Object> uniques = new List<Object>(); | ||||||
|  |         Set<Object> keys = new Set<Object>();  | ||||||
|  |         if(theList != null && theList.size() > 0){ | ||||||
|  |             for(Object obj : theList){ | ||||||
|  |                 if(keys.contains(obj)){ | ||||||
|  |                     continue; | ||||||
|  |                 } else { | ||||||
|  |                     keys.add(obj); | ||||||
|  |                     uniques.add(obj); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return uniques; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     global static List<SObject> unique(List<SObject> theList) { | ||||||
|  |         if(theList == null){ | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         List<SObject> uniques = createEmptySObjectList(theList.get(0)); | ||||||
|  |         Set<String> keys = new Set<String>();  | ||||||
|  |         if(theList != null && theList.size() > 0){ | ||||||
|  |             String key = null; | ||||||
|  |             for(SObject obj : theList){ | ||||||
|  |                 key = obj == null ? null : ''+obj; | ||||||
|  |                 if(keys.contains(key)){ | ||||||
|  |                     continue; | ||||||
|  |                 } else { | ||||||
|  |                     keys.add(key); | ||||||
|  |                     uniques.add(obj); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return uniques; | ||||||
|  |     } | ||||||
|  | */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										574
									
								
								test/fixtures/Email.cls
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										574
									
								
								test/fixtures/Email.cls
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,574 @@ | |||||||
|  |  | ||||||
|  |  /*------------------------------------------------------------------------ | ||||||
|  |     File        : Email | ||||||
|  |     Purpose     : Abstraction of an Email message | ||||||
|  |     Description : Holds information needed for an email message - senders, | ||||||
|  |                   recipients, subject, a message body, attachment files, and | ||||||
|  |                   other extra information such as importance, priority, | ||||||
|  |                   sensitivity, custom reply-to addresses, delivery receipts, | ||||||
|  |                   read receipts, custom sent date, reply-by date, and expire date. | ||||||
|  |     Author(s)   : Abe Voelker | ||||||
|  |     Created     : Sat Jul 17 16:27:05 CDT 2010 | ||||||
|  |   ----------------------------------------------------------------------*/ | ||||||
|  |  | ||||||
|  | USING Progress.Lang.*. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CLASS email.Email  USE-WIDGET-POOL: | ||||||
|  |  | ||||||
|  |     &SCOPED-DEFINE QUOTES                """" | ||||||
|  |     &SCOPED-DEFINE CR                    CHR(13) | ||||||
|  |     &SCOPED-DEFINE LF                    CHR(10) | ||||||
|  |     &SCOPED-DEFINE DEFAULT_MIME_BOUNDARY "!@#$%^&*+-._MIME_BOUNDARY_.-+*&^%$#@!" | ||||||
|  |  | ||||||
|  |     /*------------------------------------------------------------------------------ | ||||||
|  |             Purpose: | ||||||
|  |             Notes: | ||||||
|  |     ------------------------------------------------------------------------------*/ | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE VARIABLE objSendEmailAlgorithm AS email.SendEmailAlgorithm NO-UNDO. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE TEMP-TABLE ttSenders NO-UNDO | ||||||
|  |       FIELD cEmailAddress AS CHARACTER | ||||||
|  |       FIELD cRealName     AS CHARACTER INITIAL ? | ||||||
|  |       INDEX IXPK_ttSenders cEmailAddress. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE TEMP-TABLE ttToRecipients NO-UNDO | ||||||
|  |       FIELD cEmailAddress AS CHARACTER | ||||||
|  |       FIELD cRealName     AS CHARACTER INITIAL ? | ||||||
|  |       INDEX IXPK_ttToRecipients cEmailAddress. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE TEMP-TABLE ttCCRecipients NO-UNDO | ||||||
|  |       FIELD cEmailAddress AS CHARACTER | ||||||
|  |       FIELD cRealName     AS CHARACTER INITIAL ? | ||||||
|  |       INDEX IXPK_ttCCRecipients cEmailAddress. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE TEMP-TABLE ttBCCRecipients NO-UNDO | ||||||
|  |       FIELD cEmailAddress AS CHARACTER | ||||||
|  |       FIELD cRealName     AS CHARACTER INITIAL ? | ||||||
|  |       INDEX IXPK_ttBCCRecipients cEmailAddress. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE TEMP-TABLE ttReplyToRecipients NO-UNDO | ||||||
|  |       FIELD cEmailAddress AS CHARACTER | ||||||
|  |       FIELD cRealName     AS CHARACTER INITIAL ? | ||||||
|  |       INDEX IXPK_ttReplyToRecipients cEmailAddress. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE TEMP-TABLE ttReadReceiptRecipients NO-UNDO | ||||||
|  |       FIELD cEmailAddress AS CHARACTER | ||||||
|  |       FIELD cRealName     AS CHARACTER INITIAL ? | ||||||
|  |       INDEX IXPK_ttReadReceiptRecipients cEmailAddress. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE TEMP-TABLE ttDeliveryReceiptRecipients NO-UNDO | ||||||
|  |       FIELD cEmailAddress AS CHARACTER | ||||||
|  |       FIELD cRealName     AS CHARACTER INITIAL ? | ||||||
|  |       INDEX IXPK_ttDeliveryReceiptRecipients cEmailAddress. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE TEMP-TABLE ttAttachments NO-UNDO | ||||||
|  |       FIELD cFileName     AS CHARACTER | ||||||
|  |       FIELD lcData        AS Object    /* Longchar object */ | ||||||
|  |       FIELD lBase64Encode AS LOGICAL. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE VARIABLE cMimeBoundary     AS CHARACTER   NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE lcBody            AS LONGCHAR    NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE lBodyIsBase64     AS LOGICAL     NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE cSubject          AS CHARACTER   NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE mptrAttachments   AS MEMPTR      NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE cImportance       AS CHARACTER   NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE cSensitivity      AS CHARACTER   NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE cPriority         AS CHARACTER   NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE dttmtzSentDate    AS DATETIME-TZ INITIAL ? NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE dttmtzReplyByDate AS DATETIME-TZ INITIAL ? NO-UNDO. | ||||||
|  |     DEFINE PRIVATE VARIABLE dttmtzExpireDate  AS DATETIME-TZ INITIAL ? NO-UNDO. | ||||||
|  |  | ||||||
|  |     DEFINE PRIVATE VARIABLE cNewLine          AS CHARACTER   NO-UNDO. | ||||||
|  |  | ||||||
|  |     /* Other email headers: */ | ||||||
|  |  | ||||||
|  |     CONSTRUCTOR PUBLIC Email (INPUT ipobjSendEmailAlgorithm AS email.SendEmailAlgorithm): | ||||||
|  |         SUPER (). | ||||||
|  |         ASSIGN objSendEmailAlgorithm = ipobjSendEmailAlgorithm | ||||||
|  |                cMimeBoundary         = {&DEFAULT_MIME_BOUNDARY} | ||||||
|  |                lBodyIsBase64         = TRUE. | ||||||
|  |         IF (OPSYS BEGINS "WIN") THEN | ||||||
|  |             ASSIGN cNewLine          = {&CR} + {&LF}. | ||||||
|  |         ELSE | ||||||
|  |             ASSIGN cNewLine          = {&LF}. | ||||||
|  |     END CONSTRUCTOR. | ||||||
|  |  | ||||||
|  |     DESTRUCTOR PUBLIC Email (): | ||||||
|  |         FOR EACH ttAttachments: | ||||||
|  |             IF VALID-OBJECT(ttAttachments.lcData) THEN | ||||||
|  |                 DELETE OBJECT ttAttachments.lcData NO-ERROR. | ||||||
|  |         END. /* FOR EACH ttAttachments */ | ||||||
|  |     END DESTRUCTOR. | ||||||
|  |  | ||||||
|  |     /* Add a sender ("From:" address) to the email */ | ||||||
|  |     METHOD PUBLIC VOID addSender(INPUT ipcEmailAddress AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttSenders | ||||||
|  |                         WHERE ttSenders.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttSenders. | ||||||
|  |             ASSIGN ttSenders.cEmailAddress = ipcEmailAddress. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a sender ("From:" address) (with Real Name) to the email */ | ||||||
|  |     METHOD PUBLIC VOID addSender(INPUT ipcEmailAddress AS CHARACTER, | ||||||
|  |                                  INPUT ipcRealName     AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttSenders | ||||||
|  |                         WHERE ttSenders.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttSenders. | ||||||
|  |             ASSIGN ttSenders.cEmailAddress = ipcEmailAddress | ||||||
|  |                    ttSenders.cRealName     = ipcRealName. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a "To:" recipient to the email */ | ||||||
|  |     METHOD PUBLIC VOID addToRecipient(INPUT ipcEmailAddress AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttToRecipients | ||||||
|  |                         WHERE ttToRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttToRecipients. | ||||||
|  |             ASSIGN ttToRecipients.cEmailAddress = ipcEmailAddress. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a "To:" recipient (with Real Name) to the email */ | ||||||
|  |     METHOD PUBLIC VOID addToRecipient(INPUT ipcEmailAddress AS CHARACTER, | ||||||
|  |                                       INPUT ipcRealName     AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttToRecipients | ||||||
|  |                         WHERE ttToRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttToRecipients. | ||||||
|  |             ASSIGN ttToRecipients.cEmailAddress = ipcEmailAddress | ||||||
|  |                    ttToRecipients.cRealName     = ipcRealName. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a "CC:" recipient to the email */ | ||||||
|  |     METHOD PUBLIC VOID addCCRecipient(INPUT ipcEmailAddress AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttCCRecipients | ||||||
|  |                         WHERE ttCCRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttCCRecipients. | ||||||
|  |             ASSIGN ttCCRecipients.cEmailAddress = ipcEmailAddress. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a "CC:" recipient (with Real Name) to the email */ | ||||||
|  |     METHOD PUBLIC VOID addCCRecipient(INPUT ipcEmailAddress AS CHARACTER, | ||||||
|  |                                       INPUT ipcRealName     AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttCCRecipients | ||||||
|  |                         WHERE ttCCRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttCCRecipients. | ||||||
|  |             ASSIGN ttCCRecipients.cEmailAddress = ipcEmailAddress | ||||||
|  |                    ttToRecipients.cRealName     = ipcRealName. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a "BCC:" recipient to the email */ | ||||||
|  |     METHOD PUBLIC VOID addBCCRecipient(INPUT ipcEmailAddress AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttBCCRecipients | ||||||
|  |                         WHERE ttBCCRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttBCCRecipients. | ||||||
|  |             ASSIGN ttBCCRecipients.cEmailAddress = ipcEmailAddress. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a "BCC:" recipient (with Real Name) to the email */ | ||||||
|  |     METHOD PUBLIC VOID addBCCRecipient(INPUT ipcEmailAddress AS CHARACTER, | ||||||
|  |                                        INPUT ipcRealName     AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttBCCRecipients | ||||||
|  |                         WHERE ttBCCRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttBCCRecipients. | ||||||
|  |             ASSIGN ttBCCRecipients.cEmailAddress = ipcEmailAddress | ||||||
|  |                    ttToRecipients.cRealName      = ipcRealName. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a reply-to recipient to the email */ | ||||||
|  |     METHOD PUBLIC VOID addReplyToRecipient(INPUT ipcEmailAddress AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttReplyToRecipients | ||||||
|  |                         WHERE ttReplyToRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttReplyToRecipients. | ||||||
|  |             ASSIGN ttReplyToRecipients.cEmailAddress = ipcEmailAddress. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a  reply-to recipient (with Real Name) to the email */ | ||||||
|  |     METHOD PUBLIC VOID addReplyToRecipient(INPUT ipcEmailAddress AS CHARACTER, | ||||||
|  |                                            INPUT ipcRealName     AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttReplyToRecipients | ||||||
|  |                         WHERE ttReplyToRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttReplyToRecipients. | ||||||
|  |             ASSIGN ttReplyToRecipients.cEmailAddress = ipcEmailAddress | ||||||
|  |                    ttReplyToRecipients.cRealName     = ipcRealName. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a delivery receipt recipient to the email */ | ||||||
|  |     METHOD PUBLIC VOID addDeliveryReceiptRecipient(INPUT ipcEmailAddress AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttDeliveryReceiptRecipients | ||||||
|  |                         WHERE ttDeliveryReceiptRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttDeliveryReceiptRecipients. | ||||||
|  |             ASSIGN ttDeliveryReceiptRecipients.cEmailAddress = ipcEmailAddress. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a delivery receipt recipient (with Real Name) to the email */ | ||||||
|  |     METHOD PUBLIC VOID addDeliveryReceiptRecipient(INPUT ipcEmailAddress AS CHARACTER, | ||||||
|  |                                                    INPUT ipcRealName     AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttDeliveryReceiptRecipients | ||||||
|  |                         WHERE ttDeliveryReceiptRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttDeliveryReceiptRecipients. | ||||||
|  |             ASSIGN ttDeliveryReceiptRecipients.cEmailAddress = ipcEmailAddress | ||||||
|  |                    ttDeliveryReceiptRecipients.cRealName     = ipcRealName. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a read receipt recipient to the email */ | ||||||
|  |     METHOD PUBLIC VOID addReadReceiptRecipient(INPUT ipcEmailAddress AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttReadReceiptRecipients | ||||||
|  |                         WHERE ttReadReceiptRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttReadReceiptRecipients. | ||||||
|  |             ASSIGN ttReadReceiptRecipients.cEmailAddress = ipcEmailAddress. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a read receipt recipient (with Real Name) to the email */ | ||||||
|  |     METHOD PUBLIC VOID addReadReceiptRecipient(INPUT ipcEmailAddress AS CHARACTER, | ||||||
|  |                                                INPUT ipcRealName     AS CHARACTER): | ||||||
|  |         IF NOT CAN-FIND(FIRST ttReadReceiptRecipients | ||||||
|  |                         WHERE ttReadReceiptRecipients.cEmailAddress EQ ipcEmailAddress) THEN DO: | ||||||
|  |             CREATE ttReadReceiptRecipients. | ||||||
|  |             ASSIGN ttReadReceiptRecipients.cEmailAddress = ipcEmailAddress | ||||||
|  |                    ttReadReceiptRecipients.cRealName     = ipcRealName. | ||||||
|  |         END. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Set the subject of the email */ | ||||||
|  |     METHOD PUBLIC VOID setSubject(INPUT ipcSubject AS CHARACTER): | ||||||
|  |         ASSIGN cSubject = ipcSubject. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Set the importance of the email. H = High, L = Low, anything else = Medium/None */ | ||||||
|  |     METHOD PUBLIC VOID setImportance(INPUT ipcImportance AS CHARACTER): | ||||||
|  |         ASSIGN cImportance = ipcImportance. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Set the sensitivity of the email. */ | ||||||
|  |     /* Possible values (from RFC 2156): "Personal", "Private", or "Company confidential" ("Company-confidential") */ | ||||||
|  |     METHOD PUBLIC VOID setSensitivity(INPUT ipcSensitivity AS CHARACTER): | ||||||
|  |         ASSIGN cSensitivity = ipcSensitivity. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Set the priority of the email (to affect transmission speed and delivery) */ | ||||||
|  |     /* Possible values (from RFC 2156): "normal", "urgent", or "non-urgent" */ | ||||||
|  |     METHOD PUBLIC VOID setPriority(INPUT ipcPriority AS CHARACTER): | ||||||
|  |         ASSIGN cPriority = ipcPriority. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Set the date/time the email was sent */ | ||||||
|  |     METHOD PUBLIC VOID setSentDate(INPUT ipdttmtzSentDate AS DATETIME-TZ): | ||||||
|  |         ASSIGN dttmtzSentDate = ipdttmtzSentDate. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Set the date/time recipient(s) should reply by */ | ||||||
|  |     METHOD PUBLIC VOID setReplyByDate(INPUT ipdttmtzReplyByDate AS DATETIME-TZ): | ||||||
|  |         ASSIGN dttmtzReplyByDate = ipdttmtzReplyByDate. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Set the date/time the message expires */ | ||||||
|  |     METHOD PUBLIC VOID setExpireDate(INPUT ipdttmtzExpireDate AS DATETIME-TZ): | ||||||
|  |         ASSIGN dttmtzExpireDate = ipdttmtzExpireDate. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* If send email algorithm not set in constructor, you must set it using this method before the email can be sent */ | ||||||
|  |     METHOD PUBLIC VOID setSendEmailAlgorithm(INPUT ipobjSendEmailAlgorithm AS email.SendEmailAlgorithm): | ||||||
|  |         ASSIGN objSendEmailAlgorithm = ipobjSendEmailAlgorithm. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     METHOD PUBLIC VOID setBodyText(INPUT ipcBodyText AS CHARACTER): | ||||||
|  |         ASSIGN lcBody = ipcBodyText. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     METHOD PUBLIC VOID setBodyText(INPUT iplcBodyText AS LONGCHAR): | ||||||
|  |         ASSIGN lcBody = iplcBodyText. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Set the body by reading in an external file */ | ||||||
|  |     METHOD PUBLIC CHARACTER setBodyFile(INPUT ipcBodyFile AS CHARACTER): | ||||||
|  |         FILE-INFO:FILE-NAME = ipcBodyFile. | ||||||
|  |         IF FILE-INFO:FULL-PATHNAME EQ ? THEN | ||||||
|  |             RETURN "Cannot locate file '" + ipcBodyFile + "' in the filesystem!". | ||||||
|  |         IF INDEX(FILE-INFO:FILE-TYPE, "R") EQ 0 THEN | ||||||
|  |             RETURN "File '" + FILE-INFO:FULL-PATHNAME + "' exists but is not readable!". | ||||||
|  |         COPY-LOB FROM FILE FILE-INFO:FULL-PATHNAME TO OBJECT lcBody NO-ERROR. | ||||||
|  |         IF ERROR-STATUS:ERROR THEN | ||||||
|  |             RETURN "Error copying from file: " + ERROR-STATUS:GET-MESSAGE(1). | ||||||
|  |         RETURN "". /* Success */ | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Body defaults to base64 encoding, but can be manually disabled */ | ||||||
|  |     METHOD PUBLIC VOID setBodyEncoding(INPUT iplBase64Encode AS LOGICAL): | ||||||
|  |         ASSIGN lBodyIsBase64 = iplBase64Encode. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Add a non-encoded file attachment to the email */ | ||||||
|  |     METHOD PUBLIC CHARACTER addTextAttachment(INPUT ipcFileName AS CHARACTER): | ||||||
|  |         DEFINE VARIABLE lcTemp AS LONGCHAR NO-UNDO. | ||||||
|  |         FILE-INFO:FILE-NAME = ipcFileName. | ||||||
|  |         IF FILE-INFO:FULL-PATHNAME EQ ? THEN | ||||||
|  |             RETURN "Cannot locate file '" + ipcFileName + "' in the filesystem!". | ||||||
|  |         IF INDEX(FILE-INFO:FILE-TYPE, "R") EQ 0 THEN | ||||||
|  |             RETURN "File '" + FILE-INFO:FULL-PATHNAME + "' exists but is not readable!". | ||||||
|  |         /* Load file into memory */ | ||||||
|  |         COPY-LOB FROM FILE FILE-INFO:FULL-PATHNAME TO OBJECT lcTemp NO-ERROR. | ||||||
|  |         IF ERROR-STATUS:ERROR THEN | ||||||
|  |             RETURN "Error copying from file: " + ERROR-STATUS:GET-MESSAGE(1). | ||||||
|  |         CREATE ttAttachments. | ||||||
|  |         ASSIGN ttAttachments.cFileName     = ipcFileName | ||||||
|  |                ttAttachments.lcData        = NEW email.LongcharWrapper(lcTemp) | ||||||
|  |                ttAttachments.lBase64Encode = FALSE. | ||||||
|  |         RETURN "". /* Success */ | ||||||
|  |     END. | ||||||
|  |  | ||||||
|  |     /* Add a file attachment to the email; it defaults to base-64 encoding */ | ||||||
|  |     METHOD PUBLIC CHARACTER addAttachment(INPUT ipcFileName AS CHARACTER): | ||||||
|  |         DEFINE VARIABLE lcTemp AS LONGCHAR NO-UNDO. | ||||||
|  |         FILE-INFO:FILE-NAME = ipcFileName. | ||||||
|  |         IF FILE-INFO:FULL-PATHNAME EQ ? THEN | ||||||
|  |             RETURN "Cannot locate file '" + ipcFileName + "' in the filesystem!". | ||||||
|  |         IF INDEX(FILE-INFO:FILE-TYPE, "R") EQ 0 THEN | ||||||
|  |             RETURN "File '" + FILE-INFO:FULL-PATHNAME + "' exists but is not readable!". | ||||||
|  |         /* Load file into memory */ | ||||||
|  |         COPY-LOB FROM FILE FILE-INFO:FULL-PATHNAME TO OBJECT lcTemp NO-ERROR. | ||||||
|  |         IF ERROR-STATUS:ERROR THEN | ||||||
|  |             RETURN "Error copying from file: " + ERROR-STATUS:GET-MESSAGE(1). | ||||||
|  |         CREATE ttAttachments. | ||||||
|  |         ASSIGN ttAttachments.cFileName     = ipcFileName | ||||||
|  |                ttAttachments.lcData        = NEW email.LongcharWrapper(EmailClient.Util:ConvertDataToBase64(lcTemp)) | ||||||
|  |                ttAttachments.lBase64Encode = TRUE. | ||||||
|  |         RETURN "". /* Success */ | ||||||
|  |     END. | ||||||
|  |  | ||||||
|  |     /* Override default MIME boundary */ | ||||||
|  |     METHOD PUBLIC VOID setMimeBoundary(INPUT ipcMimeBoundary AS CHARACTER): | ||||||
|  |         ASSIGN cMimeBoundary = ipcMimeBoundary. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Return a concatenated list of To:, CC:, and BCC: recipients */ | ||||||
|  |     METHOD PUBLIC CHARACTER getRecipients(): | ||||||
|  |         DEFINE VARIABLE cRecipients AS CHARACTER NO-UNDO. | ||||||
|  |  | ||||||
|  |         FOR EACH ttToRecipients | ||||||
|  |           BREAK BY ttToRecipients.cEmailAddress: | ||||||
|  |             ASSIGN cRecipients = cRecipients + ttToRecipients.cEmailAddress. | ||||||
|  |             IF NOT LAST(ttToRecipients.cEmailAddress) THEN DO: | ||||||
|  |                 ASSIGN cRecipients = cRecipients + ", ". | ||||||
|  |             END. | ||||||
|  |         END. | ||||||
|  |         FOR EACH ttCCRecipients | ||||||
|  |           BREAK BY ttCCRecipients.cEmailAddress: | ||||||
|  |             IF FIRST(ttCCRecipients.cEmailAddress) AND | ||||||
|  |                cRecipients NE "" THEN | ||||||
|  |                 ASSIGN cRecipients = cRecipients + ", ". | ||||||
|  |             ASSIGN cRecipients = cRecipients + ttCCRecipients.cEmailAddress. | ||||||
|  |             IF NOT LAST(ttCCRecipients.cEmailAddress) THEN | ||||||
|  |                 ASSIGN cRecipients = cRecipients + ttCCRecipients.cEmailAddress. | ||||||
|  |         END. | ||||||
|  |         FOR EACH ttBCCRecipients | ||||||
|  |           BREAK BY ttBCCRecipients.cEmailAddress: | ||||||
|  |             IF FIRST(ttBCCRecipients.cEmailAddress) AND | ||||||
|  |                cRecipients NE "" THEN | ||||||
|  |                 ASSIGN cRecipients = cRecipients + ", ". | ||||||
|  |             ASSIGN cRecipients = cRecipients + ttBCCRecipients.cEmailAddress. | ||||||
|  |             IF NOT LAST(ttBCCRecipients.cEmailAddress) THEN | ||||||
|  |                 ASSIGN cRecipients = cRecipients + ttBCCRecipients.cEmailAddress. | ||||||
|  |         END. | ||||||
|  |         RETURN cRecipients. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Dumps all email message headers to CHAR */ | ||||||
|  |     METHOD PUBLIC CHARACTER getHeaders(): | ||||||
|  |         DEFINE VARIABLE cReturnData AS CHARACTER NO-UNDO. | ||||||
|  |  | ||||||
|  |         /* Write the "From:" header */ | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "From:". | ||||||
|  |         FOR EACH ttSenders | ||||||
|  |           BREAK BY ttSenders.cEmailAddress: | ||||||
|  |             IF ttSenders.cRealName NE ? THEN | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ttSenders.cRealName + " <" + ttSenders.cEmailAddress + ">". | ||||||
|  |             ELSE | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ttSenders.cEmailAddress. | ||||||
|  |             IF NOT LAST(ttSenders.cEmailAddress) THEN | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ", ". | ||||||
|  |         END. | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "\n". | ||||||
|  |         /* Write the "To:" header */ | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "To:". | ||||||
|  |         FOR EACH ttToRecipients | ||||||
|  |           BREAK BY ttToRecipients.cEmailAddress: | ||||||
|  |             IF ttToRecipients.cRealName NE ? THEN | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ttToRecipients.cRealName + " <" + ttToRecipients.cEmailAddress + ">". | ||||||
|  |             ELSE | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ttToRecipients.cEmailAddress. | ||||||
|  |             IF NOT LAST(ttToRecipients.cEmailAddress) THEN | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ", ". | ||||||
|  |         END. | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "\n". | ||||||
|  |         /* Write the "Reply-To:" header */ | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "Reply-To:". | ||||||
|  |         IF TEMP-TABLE ttReplyToRecipients:HAS-RECORDS THEN DO: | ||||||
|  |             /* Use manually-overridden reply-to addresses */ | ||||||
|  |             FOR EACH ttReplyToRecipients | ||||||
|  |               BREAK BY ttReplyToRecipients.cEmailAddress: | ||||||
|  |                 IF ttReplyToRecipients.cRealName NE ? THEN | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ttReplyToRecipients.cRealName + " <" + ttReplyToRecipients.cEmailAddress + ">". | ||||||
|  |                 ELSE | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ttReplyToRecipients.cEmailAddress. | ||||||
|  |                 IF NOT LAST(ttReplyToRecipients.cEmailAddress) THEN | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ", ". | ||||||
|  |             END. /* FOR EACH ttReplyToRecipients ... */ | ||||||
|  |         END. /* IF TEMP-TABLE ttReplyToRecipients:HAS-RECORDS */ | ||||||
|  |         ELSE DO: | ||||||
|  |             /* Write reply-to using sender addresses if reply-to addresses not manually overriddden */ | ||||||
|  |             FOR EACH ttSenders | ||||||
|  |               BREAK BY ttSenders.cEmailAddress: | ||||||
|  |                 IF ttSenders.cRealName NE ? THEN | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ttSenders.cRealName + " <" + ttSenders.cEmailAddress + ">". | ||||||
|  |                 ELSE | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ttSenders.cEmailAddress. | ||||||
|  |                 IF NOT LAST(ttSenders.cEmailAddress) THEN | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ", ". | ||||||
|  |             END. | ||||||
|  |         END. /* ELSE / IF TEMP-TABLE ttReplyToRecipients:HAS-RECORDS */ | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "\n". | ||||||
|  |         /* Write the "Cc:" header */ | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "Cc:". | ||||||
|  |         FOR EACH ttCCRecipients | ||||||
|  |           BREAK BY ttCCRecipients.cEmailAddress: | ||||||
|  |             IF ttCCRecipients.cRealName NE ? THEN | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ttCCRecipients.cRealName + " <" + ttCCRecipients.cEmailAddress + ">". | ||||||
|  |             ELSE | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ttCCRecipients.cEmailAddress. | ||||||
|  |             IF NOT LAST(ttCCRecipients.cEmailAddress) THEN | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ", ". | ||||||
|  |         END. | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "\n". | ||||||
|  |         /* Write the "Bcc:" header */ | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "Bcc:". | ||||||
|  |         FOR EACH ttBCCRecipients | ||||||
|  |           BREAK BY ttBCCRecipients.cEmailAddress: | ||||||
|  |             IF ttBCCRecipients.cRealName NE ? THEN | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ttBCCRecipients.cRealName + " <" + ttBCCRecipients.cEmailAddress + ">". | ||||||
|  |             ELSE | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ttBCCRecipients.cEmailAddress. | ||||||
|  |             IF NOT LAST(ttBCCRecipients.cEmailAddress) THEN | ||||||
|  |                 ASSIGN cReturnData = cReturnData + ", ". | ||||||
|  |         END. | ||||||
|  |         ASSIGN cReturnData = cReturnData + {"ES} + "\n". | ||||||
|  |         /* If delivery recipients specified, write each recipient out */ | ||||||
|  |         IF TEMP-TABLE ttDeliveryReceiptRecipients:HAS-RECORDS THEN DO: | ||||||
|  |             ASSIGN cReturnData = cReturnData + {"ES} + "Return-Receipt-To:". | ||||||
|  |             FOR EACH ttDeliveryReceiptRecipients | ||||||
|  |               BREAK BY ttDeliveryReceiptRecipients.cEmailAddress: | ||||||
|  |                 IF ttDeliveryReceiptRecipients.cRealName NE ? THEN | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ttDeliveryReceiptRecipients.cRealName + " <" + ttDeliveryReceiptRecipients.cEmailAddress + ">". | ||||||
|  |                 ELSE | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ttDeliveryReceiptRecipients.cEmailAddress. | ||||||
|  |                 IF NOT LAST(ttDeliveryReceiptRecipients.cEmailAddress) THEN | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ", ". | ||||||
|  |             END. /* FOR EACH ttDeliveryReceiptRecipients */ | ||||||
|  |             ASSIGN cReturnData = cReturnData + {"ES}. | ||||||
|  |         END. /* IF TEMP-TABLE ttDeliveryReceiptRecipients:HAS-RECORDS */ | ||||||
|  |         /* If read recipients specified, write each recipient out */ | ||||||
|  |         IF TEMP-TABLE ttReadReceiptRecipients:HAS-RECORDS THEN DO: | ||||||
|  |             ASSIGN cReturnData = cReturnData + {"ES} + "Disposition-Notification-To:". | ||||||
|  |             FOR EACH ttReadReceiptRecipients | ||||||
|  |               BREAK BY ttReadReceiptRecipients.cEmailAddress: | ||||||
|  |                 IF ttReadReceiptRecipients.cRealName NE ? THEN | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ttReadReceiptRecipients.cRealName + " <" + ttReadReceiptRecipients.cEmailAddress + ">". | ||||||
|  |                 ELSE | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ttReadReceiptRecipients.cEmailAddress. | ||||||
|  |                 IF NOT LAST(ttReadReceiptRecipients.cEmailAddress) THEN | ||||||
|  |                     ASSIGN cReturnData = cReturnData + ", ". | ||||||
|  |             END. /* FOR EACH ttReadReceiptRecipients */ | ||||||
|  |             ASSIGN cReturnData = cReturnData + {"ES}. | ||||||
|  |         END. /* IF TEMP-TABLE ttReadReceiptRecipients:HAS-RECORDS */ | ||||||
|  |         /* Write the "Subject:" header */ | ||||||
|  |         ASSIGN cReturnData = cReturnData + "\n" + {"ES} + "Subject:" + cSubject + {"ES}. | ||||||
|  |         /* Write the "Importance:" header */ | ||||||
|  |         IF cImportance BEGINS "H" THEN | ||||||
|  |             ASSIGN cReturnData = cReturnData + "\n" + {"ES} + "Importance:High" + {"ES}. | ||||||
|  |         ELSE IF cImportance BEGINS "L" THEN | ||||||
|  |             ASSIGN cReturnData = cReturnData + "\n" + {"ES} + "Importance:Low" + {"ES}. | ||||||
|  |         /* Write the "Sensitivity" header */ | ||||||
|  |         IF cSensitivity NE "" THEN | ||||||
|  |             ASSIGN cReturnData = cReturnData + "\n" + {"ES} + "Sensitivity:" + cSensitivity + {"ES}. | ||||||
|  |         /* Write the "Priority" header */ | ||||||
|  |         IF cPriority NE "" THEN | ||||||
|  |             ASSIGN cReturnData = cReturnData + "\n" + {"ES} + "Priority:" + cPriority + {"ES}. | ||||||
|  |         /* Write the "Date" (sent date) header */ | ||||||
|  |         IF dttmtzSentDate NE ? THEN | ||||||
|  |             ASSIGN cReturnData = cReturnData + "\n" + {"ES} + "Date:" + email.Util:ABLDateTimeToEmail(dttmtzSentDate) + {"ES}. | ||||||
|  |         IF dttmtzReplyByDate NE ? THEN | ||||||
|  |             ASSIGN cReturnData = cReturnData + "\n" + {"ES} + "Reply-By:" + email.Util:ABLDateTimeToEmail(dttmtzReplyByDate) + {"ES}. | ||||||
|  |         /* Write the "Expiry-Date" header */ | ||||||
|  |         IF dttmtzExpireDate NE ? THEN | ||||||
|  |             ASSIGN cReturnData = cReturnData + "\n" + {"ES} + "Expiry-Date:" + email.Util:ABLDateTimeToEmail(dttmtzExpireDate) + {"ES}. | ||||||
|  |         RETURN cReturnData. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     /* Dumps all email message payload data (body and attachments) to LONGCHAR */ | ||||||
|  |     METHOD PUBLIC LONGCHAR getPayload(): | ||||||
|  |         DEFINE VARIABLE lcReturnData AS LONGCHAR NO-UNDO. | ||||||
|  |  | ||||||
|  |         /* If no body and no text, then return empty string ("") */ | ||||||
|  |         IF lcBody EQ "" AND NOT TEMP-TABLE ttAttachments:HAS-RECORDS THEN | ||||||
|  |             RETURN lcReturnData. | ||||||
|  |  | ||||||
|  |         /* Write payload header */ | ||||||
|  |         ASSIGN lcReturnData = "Mime-Version: 1.0" + cNewLine + | ||||||
|  |                               "Content-Type: multipart/mixed; boundary=" + cMimeBoundary + cNewLine + cNewLine. | ||||||
|  |  | ||||||
|  |         /* Write out the email body, if it exists */ | ||||||
|  |         IF lcBody NE "" THEN DO: | ||||||
|  |             ASSIGN lcReturnData = lcReturnData + "--" + cMimeBoundary + cNewLine + | ||||||
|  |                                   "Content-Type: text/plain; charset=~"us-ascii~"" + cNewLine. | ||||||
|  |             IF lBodyIsBase64 THEN DO: | ||||||
|  |                 ASSIGN lcReturnData = lcReturnData + "Content-Transfer-Encoding: base64" + cNewLine + | ||||||
|  |                                       cNewLine + | ||||||
|  |                                       email.Util:ConvertDataToBase64(lcBody) + cNewLine. | ||||||
|  |             END. | ||||||
|  |             ELSE DO: | ||||||
|  |                 ASSIGN lcReturnData = lcReturnData + "Content-Transfer-Encoding: 7bit"   + cNewLine + | ||||||
|  |                                       cNewLine + | ||||||
|  |                                       lcBody + cNewLine. | ||||||
|  |             END. | ||||||
|  |         END. | ||||||
|  |  | ||||||
|  |         /* Write out each email attachment */ | ||||||
|  |         FOR EACH ttAttachments: | ||||||
|  |             ASSIGN lcReturnData = lcReturnData + "--" + cMimeBoundary + cNewLine. | ||||||
|  |             IF ttAttachments.lBase64Encode THEN DO: | ||||||
|  |                 ASSIGN lcReturnData = lcReturnData + "Content-Type: application/octet-stream" + cNewLine + | ||||||
|  |                                       "Content-Disposition: attachment; filename=~"" + ttAttachments.cFileName + "~"" + cNewLine + | ||||||
|  |                                       "Content-Transfer-Encoding: base64" + cNewLine + cNewLine + | ||||||
|  |                                       CAST(ttAttachments.lcData, email.LongcharWrapper):getLongchar() + cNewLine. | ||||||
|  |             END. | ||||||
|  |             ELSE DO: | ||||||
|  |                 ASSIGN lcReturnData = lcReturnData + "Content-Type: text/plain; charset=~"us-ascii~"" + cNewLine + | ||||||
|  |                                       "Content-Disposition: attachment; filename=~"" + ttAttachments.cFileName + "~"" + cNewLine + | ||||||
|  |                                       "Content-Transfer-Encoding: 7bit" + cNewLine + cNewLine + | ||||||
|  |                                       CAST(ttAttachments.lcData, email.LongcharWrapper):getLongchar() + cNewLine. | ||||||
|  |             END. | ||||||
|  |         END. | ||||||
|  |  | ||||||
|  |         /* Write payload footer */ | ||||||
|  |         ASSIGN lcReturnData = lcReturnData + "--" + cMimeBoundary + "--" + cNewLine. | ||||||
|  |  | ||||||
|  |         RETURN lcReturnData. | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  |     METHOD PUBLIC CHARACTER send(): | ||||||
|  |         RETURN objSendEmailAlgorithm:sendEmail(INPUT THIS-OBJECT). | ||||||
|  |     END METHOD. | ||||||
|  |  | ||||||
|  | END CLASS. | ||||||
							
								
								
									
										240
									
								
								test/fixtures/cApplication.cls
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								test/fixtures/cApplication.cls
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,240 @@ | |||||||
|  | VERSION 1.0 CLASS | ||||||
|  | BEGIN | ||||||
|  |   MultiUse = -1  'True | ||||||
|  |   Persistable = 0  'NotPersistable | ||||||
|  |   DataBindingBehavior = 0  'vbNone | ||||||
|  |   DataSourceBehavior  = 0  'vbNone | ||||||
|  |   MTSTransactionMode  = 0  'NotAnMTSObject | ||||||
|  | END | ||||||
|  | Attribute VB_Name = "cApplication" | ||||||
|  | Attribute VB_GlobalNameSpace = False | ||||||
|  | Attribute VB_Creatable = True | ||||||
|  | Attribute VB_PredeclaredId = False | ||||||
|  | Attribute VB_Exposed = False | ||||||
|  | '************************************************************************************************************************************************************************************************************************************************* | ||||||
|  | ' | ||||||
|  | ' Copyright (c) David Briant 2009-2012 - All rights reserved | ||||||
|  | ' | ||||||
|  | '************************************************************************************************************************************************************************************************************************************************* | ||||||
|  |  | ||||||
|  | Option Explicit | ||||||
|  |  | ||||||
|  | Private Declare Function apiSetProp Lib "user32" Alias "SetPropA" (ByVal hwnd As Long, ByVal lpString As String, ByVal hData As Long) As Long | ||||||
|  | Private Declare Function apiGlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal lpString As String) As Long | ||||||
|  | Private Declare Function apiSetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hwnd As Long) As Long | ||||||
|  |  | ||||||
|  | Private myMouseEventsForm As fMouseEventsForm | ||||||
|  | Private WithEvents myAST As cTP_AdvSysTray | ||||||
|  | Attribute myAST.VB_VarHelpID = -1 | ||||||
|  |  | ||||||
|  | Private myClassName As String | ||||||
|  | Private myWindowName As String | ||||||
|  | Private Const TEN_MILLION As Single = 10000000 | ||||||
|  |  | ||||||
|  | Private WithEvents myListener As VLMessaging.VLMMMFileListener | ||||||
|  | Attribute myListener.VB_VarHelpID = -1 | ||||||
|  | Private WithEvents myMMFileTransports As VLMessaging.VLMMMFileTransports | ||||||
|  | Attribute myMMFileTransports.VB_VarHelpID = -1 | ||||||
|  |  | ||||||
|  | Private myMachineID As Long | ||||||
|  |  | ||||||
|  | Private myRouterSeed As Long | ||||||
|  | Private myRouterIDsByMMTransportID As New Dictionary | ||||||
|  | Private myMMTransportIDsByRouterID As New Dictionary | ||||||
|  |  | ||||||
|  | Private myDirectoryEntriesByIDString As New Dictionary | ||||||
|  |  | ||||||
|  | Private Const GET_ROUTER_ID As String = "GET_ROUTER_ID" | ||||||
|  | Private Const GET_ROUTER_ID_REPLY As String = "GET_ROUTER_ID_REPLY" | ||||||
|  | Private Const REGISTER_SERVICE As String = "REGISTER_SERVICE" | ||||||
|  | Private Const REGISTER_SERVICE_REPLY As String = "REGISTER_SERVICE_REPLY" | ||||||
|  | Private Const UNREGISTER_SERVICE As String = "UNREGISTER_SERVICE" | ||||||
|  | Private Const UNREGISTER_SERVICE_REPLY As String = "UNREGISTER_SERVICE_REPLY" | ||||||
|  | Private Const GET_SERVICES As String = "GET_SERVICES" | ||||||
|  | Private Const GET_SERVICES_REPLY As String = "GET_SERVICES_REPLY" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | '************************************************************************************************************************************************************************************************************************************************* | ||||||
|  | ' Initialize / Release | ||||||
|  | '************************************************************************************************************************************************************************************************************************************************* | ||||||
|  |  | ||||||
|  | Private Sub class_Initialize() | ||||||
|  |     Dim atomID As Long | ||||||
|  |     Randomize | ||||||
|  |     ' hide us from the Applications list in the Windows Task Manager | ||||||
|  |     App.TaskVisible = False | ||||||
|  |      | ||||||
|  |     ' listen for connections | ||||||
|  |     myClassName = "VLMMachineRouter" & CStr(Int(Rnd() * TEN_MILLION) + 1) | ||||||
|  |     Randomize | ||||||
|  |     myWindowName = "VLMMachineRouter" & CStr(Int(Rnd() * TEN_MILLION) + 1) | ||||||
|  |     Set myListener = New VLMMMFileListener | ||||||
|  |     myListener.listenViaNamedWindow myClassName, myWindowName, 1024 * 8 | ||||||
|  |     Set myMMFileTransports = New VLMMMFileTransports | ||||||
|  |     myRouterSeed = 1 | ||||||
|  |      | ||||||
|  |     ' create tray icon | ||||||
|  |     Set myMouseEventsForm = New fMouseEventsForm | ||||||
|  |     Set myAST = New cTP_AdvSysTray | ||||||
|  |     myAST.create myMouseEventsForm, myMouseEventsForm.icon, "VLM Directory" | ||||||
|  |     'myAST.showBalloon "Current Shell32.dll version is " & myAST.shellVersion & ".x", "AdvSysTray VB Class", NIIF_INFO | ||||||
|  |      | ||||||
|  |     ' make myself easily found | ||||||
|  |     apiSetProp myMouseEventsForm.hwnd, "IsVLMachineRouter", 1 | ||||||
|  |     apiSetProp myMouseEventsForm.hwnd, "WindowNameAtom", apiGlobalAddAtom(myWindowName) | ||||||
|  |     apiSetProp myMouseEventsForm.hwnd, "ClassNameAtom", apiGlobalAddAtom(myClassName) | ||||||
|  |      | ||||||
|  | End Sub | ||||||
|  |  | ||||||
|  | Sub shutdown() | ||||||
|  |     myAST.destroy | ||||||
|  |     Set myAST = Nothing | ||||||
|  |     Unload myMouseEventsForm | ||||||
|  |     Set myMouseEventsForm = Nothing | ||||||
|  | End Sub | ||||||
|  |  | ||||||
|  | Private Sub myAST_RButtonUp() | ||||||
|  |     Dim epm As New cTP_EasyPopupMenu, menuItemSelected As Long | ||||||
|  |     'SetForegroundWindow myMouseEventsForm.hwnd | ||||||
|  | '    epm.addMenuItem "Main form...", MF_STRING, 1 | ||||||
|  | '    epm.createSubmenu "Radio items" | ||||||
|  | '    epm.addSubmenuItem "Radio item 1", MF_STRING, 2 | ||||||
|  | '    epm.addSubmenuItem "Radio item 2", MF_STRING, 3 | ||||||
|  | '    epm.addSubmenuItem "Radio item 3", MF_STRING, 4 | ||||||
|  | '    epm.checkRadioItem 0, 2, 1 | ||||||
|  | '    epm.addMenuItem "", MF_SEPARATOR, 0 | ||||||
|  | '    epm.addMenuItem "Disabled item", MF_GRAYED, 5 | ||||||
|  | '    epm.addMenuItem "Checked item", MF_CHECKED, 6 | ||||||
|  | '    epm.addMenuItem "", MF_SEPARATOR, 0 | ||||||
|  |     epm.addMenuItem "Exit", MF_STRING, 12 | ||||||
|  |     apiSetForegroundWindow myMouseEventsForm.hwnd | ||||||
|  |     menuItemSelected = epm.trackMenu(myMouseEventsForm.hwnd) | ||||||
|  |     Select Case menuItemSelected | ||||||
|  |         Case 12 | ||||||
|  |             Set epm = Nothing | ||||||
|  |             globalShutdown | ||||||
|  |     End Select | ||||||
|  | End Sub | ||||||
|  |  | ||||||
|  | Private Sub myListener_newConnection(ByVal newTransport As VLMessaging.VLMMMFileTransport, oReceived As Boolean) | ||||||
|  |     Dim id As Long | ||||||
|  |     oReceived = True | ||||||
|  |     id = myMMFileTransports.addTransport(newTransport) | ||||||
|  | End Sub | ||||||
|  |  | ||||||
|  | Private Function messageFromBytes(buffer() As Byte) As VLMMessage | ||||||
|  |     Dim i1 As Long, i2 As Long, messageArray As Variant, message As New VLMMessage | ||||||
|  |     DBGetArrayBounds buffer, 1, i1, i2 | ||||||
|  |     messageArray = g_VLMUtils.BytesAsVariant(buffer, i2 + 1, 1) | ||||||
|  |     message.fromMessageArray messageArray | ||||||
|  |     Set messageFromBytes = message | ||||||
|  | End Function | ||||||
|  |  | ||||||
|  | Private Function messageToBytes(message As VLMMessage) As Byte() | ||||||
|  |     Dim messageArray As Variant, length As Long, buffer() As Byte | ||||||
|  |     message.toMessageArray messageArray | ||||||
|  |     length = g_VLMUtils.LengthOfVariantAsBytes(messageArray) | ||||||
|  |     DBCreateNewArrayOfBytes buffer, 1, length | ||||||
|  |     g_VLMUtils.VariantAsBytes messageArray, buffer, length + 1, 1 | ||||||
|  |     messageToBytes = buffer | ||||||
|  | End Function | ||||||
|  |  | ||||||
|  | Private Sub myMMFileTransports_bytesArrived(ByVal id As Long, buffer() As Byte, oReceived As Boolean) | ||||||
|  |     Dim message As VLMMessage, toAddress As VLMAddress | ||||||
|  |     oReceived = True | ||||||
|  |     Set message = messageFromBytes(buffer) | ||||||
|  |     Set toAddress = message.toAddress | ||||||
|  |     On Error GoTo errorHandler | ||||||
|  |     If (toAddress.MachineID = myMachineID Or toAddress.MachineID = 0) And toAddress.RouterID = 1 And toAddress.AgentID = 1 Then | ||||||
|  |         handleMessageToRouter id, message | ||||||
|  |     Else | ||||||
|  |         routeMessage message | ||||||
|  |     End If | ||||||
|  | Exit Sub | ||||||
|  | errorHandler: | ||||||
|  |     MsgBox Err.Description & ", " & Erl | ||||||
|  | End Sub | ||||||
|  |  | ||||||
|  | Sub handleMessageToRouter(MMFileTransportID As Long, message As VLMMessage) | ||||||
|  |     Dim reply As VLMMessage, transport As VLMMMFileTransport, RouterID As Long, address As New VLMAddress | ||||||
|  |     Dim IDString As String, vs As Variant, i As Long, entries As New Collection, answer1D As Variant | ||||||
|  |      | ||||||
|  |     Select Case True | ||||||
|  |      | ||||||
|  |         Case message.subject = GET_ROUTER_ID | ||||||
|  |             If myRouterIDsByMMTransportID.Exists(MMFileTransportID) Then | ||||||
|  |                 RouterID = myRouterIDsByMMTransportID(MMFileTransportID) | ||||||
|  |             Else | ||||||
|  |                 myRouterSeed = myRouterSeed + 1 | ||||||
|  |                 RouterID = myRouterSeed | ||||||
|  |                 myRouterIDsByMMTransportID(MMFileTransportID) = RouterID | ||||||
|  |                 myMMTransportIDsByRouterID(RouterID) = MMFileTransportID | ||||||
|  |             End If | ||||||
|  |             Set reply = message.reply | ||||||
|  |             reply.subject = GET_ROUTER_ID_REPLY | ||||||
|  |             reply.Contents = RouterID | ||||||
|  |             Set transport = myMMFileTransports.transport(MMFileTransportID) | ||||||
|  |             transport.send messageToBytes(reply) | ||||||
|  |              | ||||||
|  |         Case message.subject = REGISTER_SERVICE | ||||||
|  |             address.initialise CLng(message.Contents(1)(1)), CLng(message.Contents(1)(2)), CLng(message.Contents(1)(3)) | ||||||
|  |             myDirectoryEntriesByIDString(directoryEntryIDString(CStr(message.Contents(2)), address)) = message.Contents | ||||||
|  |             Set reply = message.reply | ||||||
|  |             reply.subject = REGISTER_SERVICE_REPLY | ||||||
|  |             Set transport = myMMFileTransports.transport(MMFileTransportID) | ||||||
|  |             transport.send messageToBytes(reply) | ||||||
|  |          | ||||||
|  |         Case message.subject = UNREGISTER_SERVICE | ||||||
|  |             address.initialise CLng(message.Contents(1)(1)), CLng(message.Contents(1)(2)), CLng(message.Contents(1)(3)) | ||||||
|  |             IDString = directoryEntryIDString(CStr(message.Contents(2)), address) | ||||||
|  |             If myDirectoryEntriesByIDString.Exists(IDString) Then myDirectoryEntriesByIDString.Remove IDString | ||||||
|  |             Set reply = message.reply | ||||||
|  |             reply.subject = UNREGISTER_SERVICE_REPLY | ||||||
|  |             Set transport = myMMFileTransports.transport(MMFileTransportID) | ||||||
|  |             transport.send messageToBytes(reply) | ||||||
|  |          | ||||||
|  |         Case message.subject = GET_SERVICES | ||||||
|  |             vs = myDirectoryEntriesByIDString.Items | ||||||
|  |             For i = 0 To UBound(vs) | ||||||
|  |                 If IsEmpty(message.Contents) Then | ||||||
|  |                     entries.Add vs(i) | ||||||
|  |                 Else | ||||||
|  |                     If vs(i)(2) = message.Contents Then entries.Add vs(i) | ||||||
|  |                 End If | ||||||
|  |             Next | ||||||
|  |             If entries.Count > 0 Then | ||||||
|  |                 ReDim answer1D(1 To entries.Count) | ||||||
|  |                 For i = 1 To entries.Count | ||||||
|  |                     answer1D(i) = entries(i) | ||||||
|  |                 Next | ||||||
|  |             End If | ||||||
|  |             Set reply = message.reply | ||||||
|  |             reply.subject = GET_SERVICES_REPLY | ||||||
|  |             reply.Contents = answer1D | ||||||
|  |             Set transport = myMMFileTransports.transport(MMFileTransportID) | ||||||
|  |             transport.send messageToBytes(reply) | ||||||
|  |              | ||||||
|  |     End Select | ||||||
|  |  | ||||||
|  | End Sub | ||||||
|  |  | ||||||
|  | Sub routeMessage(message As VLMMessage) | ||||||
|  |     Dim buffer() As Byte, transport As VLMMMFileTransport | ||||||
|  |     If message.toAddress.MachineID <> 0 And message.toAddress.MachineID <> myMachineID Then | ||||||
|  |         ' route to a remote machine | ||||||
|  |     Else | ||||||
|  |         ' for the moment just route between MMFileTransports | ||||||
|  |         If myMMTransportIDsByRouterID.Exists(message.toAddress.RouterID) Then | ||||||
|  |             Set transport = myMMFileTransports(myMMTransportIDsByRouterID(message.toAddress.RouterID)) | ||||||
|  |             transport.send messageToBytes(message) | ||||||
|  |         End If | ||||||
|  |     End If | ||||||
|  | End Sub | ||||||
|  |  | ||||||
|  | Function directoryEntryIDString(serviceType As String, address As VLMAddress) | ||||||
|  |     directoryEntryIDString = serviceType & "<" & address.MachineID & "," & address.RouterID & "," & address.AgentID & ">" | ||||||
|  | End Function | ||||||
|  |  | ||||||
|  | Private Sub myMMFileTransports_disconnecting(ByVal id As Long, oReceived As Boolean) | ||||||
|  |     oReceived = True | ||||||
|  | End Sub | ||||||
							
								
								
									
										8
									
								
								test/fixtures/latex.cls
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								test/fixtures/latex.cls
									
									
									
									
										vendored
									
									
								
							| @@ -1,8 +0,0 @@ | |||||||
| % latex.cls |  | ||||||
| % |  | ||||||
| % A barebones LaTeX2e class file |  | ||||||
|  |  | ||||||
| \def\author{Abe Voelker} |  | ||||||
| \def\fileversion{0.1} |  | ||||||
| \NeedsTeXFormat{LaTeX2e} |  | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								test/fixtures/openedge.cls
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								test/fixtures/openedge.cls
									
									
									
									
										vendored
									
									
								
							| @@ -1,10 +0,0 @@ | |||||||
| USING Progress.Lang.*. |  | ||||||
|  |  | ||||||
| CLASS HelloWorld: |  | ||||||
|  |  | ||||||
|   CONSTRUCTOR PUBLIC HelloWorld(): |  | ||||||
|     SUPER(). |  | ||||||
|     MESSAGE "Hello, world!". |  | ||||||
|   END CONSTRUCTOR. |  | ||||||
|  |  | ||||||
| END CLASS. |  | ||||||
							
								
								
									
										245
									
								
								test/fixtures/reedthesis.cls
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								test/fixtures/reedthesis.cls
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | |||||||
|  | % | ||||||
|  | % This file is copyright (C) 2003 Sam Noble. It may be modified so long | ||||||
|  | % as my name is not removed and the modifier adds his name to the file. | ||||||
|  | % Redistribution permitted. | ||||||
|  | % | ||||||
|  | % 27 Jan 2004	Sam Noble	Removed tocbibind dependency. | ||||||
|  | % 04 Dec 2001 	Sam Noble	Class file | ||||||
|  | % 03 Sep 1995	David Perkinson	Title Page | ||||||
|  | % Acknowledgements Page, David Perkinson & Sam Noble | ||||||
|  | % May 2005 Patrick Carlisle Table of contents chapter definition | ||||||
|  | % 2004-2005 Ben Salzberg (BTS) a variety of tweaks here and in the template | ||||||
|  | % | ||||||
|  | % Oddities: | ||||||
|  | % | ||||||
|  | %   We *ASSUME* that any time \cleardoublepage is called | ||||||
|  | %  we actually want a blank back side with NO page number/heading | ||||||
|  | % | ||||||
|  | %   Minor bug -- seems to be a more general LaTeX thing: | ||||||
|  | %  If you use \frontmatter \mainmatter without any chapters inbetween | ||||||
|  | %  be prepared to have the page numbering messed up. Not a big deal, | ||||||
|  | %  but I'm not sure how to fix it. | ||||||
|  | % | ||||||
|  | % | ||||||
|  |  | ||||||
|  | \NeedsTeXFormat{LaTeX2e} | ||||||
|  | \ProvidesClass{reedthesis}[2004/01/27 The Reed College Thesis Class] | ||||||
|  | \DeclareOption*{\PassOptionsToClass{\CurrentOption}{book}} | ||||||
|  | \ProcessOptions\relax | ||||||
|  | \LoadClass{book} | ||||||
|  | \RequirePackage{fancyhdr} | ||||||
|  |  | ||||||
|  | % This gives us rules below the headers | ||||||
|  | \AtBeginDocument{% | ||||||
|  |   \fancyhf{} | ||||||
|  |   \fancyhead[LE,RO]{\thepage} | ||||||
|  | %  \fancyhead[RE]{\slshape \leftmark} | ||||||
|  | %  \fancyhead[LO]{\slshape \rightmark} | ||||||
|  | %	The above makes your headers in all caps. If you would like different headers, choose one of the following options (be sure to remove the % symbol from both the right and left headers): | ||||||
|  | 	 \fancyhead[RE]{\slshape \nouppercase \leftmark} % This makes the headers on the RIGHT side pages be italic and use lowercase With Capitals When Specified. | ||||||
|  | 	\fancyhead[LO]{\slshape \nouppercase \rightmark} % This does the same thing to the LEFT side pages | ||||||
|  | %	or | ||||||
|  | %	\fancyhead[RE]{\scshape \leftmark} % The RIGHT headers will be in small caps. | ||||||
|  | %	\fancyhead[LO]{\scshape \rightmark} %  And so will the LEFT headers | ||||||
|  |   \pagestyle{fancy} | ||||||
|  |  | ||||||
|  | % Psych majors: You do not need the following six lines, as it conflicts with apacite, so comment them out. | ||||||
|  |   \let\oldthebibliography=\thebibliography | ||||||
|  |   \let\endoldthebibliography=\endthebibliography | ||||||
|  |   \renewenvironment{thebibliography}[1]{ | ||||||
|  |     \oldthebibliography{#1} | ||||||
|  |     \addcontentsline{toc}{chapter}{\bibname} | ||||||
|  |   }{\endoldthebibliography} | ||||||
|  |  %%%%%% end of things for psych majors to comment out | ||||||
|  |    | ||||||
|  |   \let\oldtheindex=\theindex | ||||||
|  |   \let\endoldtheindex=\endtheindex | ||||||
|  |   \renewenvironment{theindex}{ | ||||||
|  |     \oldtheindex | ||||||
|  |     \addcontentsline{toc}{chapter}{\indexname} | ||||||
|  |   }{\endoldtheindex} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | % Stolen from book.cls and modified | ||||||
|  | \let\RToldchapter\chapter | ||||||
|  | \renewcommand{\chapter}{\if@openright\RTcleardoublepage | ||||||
|  | 		    \else\clearpage\fi | ||||||
|  | 		    \thispagestyle{empty}% | ||||||
|  | 		    \global\@topnum\z@ | ||||||
|  | 		    \@afterindentfalse | ||||||
|  | 		    \secdef\@chapter\@schapter} | ||||||
|  | 		     | ||||||
|  | % Stolen from book.cls PBC 5/12/05 | ||||||
|  | % Using this to actually show "Chapter 1" in TOC instead of "1" | ||||||
|  | \def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne | ||||||
|  |                        \if@mainmatter | ||||||
|  |                          \refstepcounter{chapter}% | ||||||
|  |                          \typeout{\@chapapp\space\thechapter.}% | ||||||
|  |                          \addcontentsline{toc}{chapter}% | ||||||
|  |                          {\@chapapp\space\thechapter:\space#1}% | ||||||
|  |                        \else | ||||||
|  |                          \addcontentsline{toc}{chapter}{#1}% | ||||||
|  |                        \fi | ||||||
|  |                     \else | ||||||
|  |                       \addcontentsline{toc}{chapter}{#1}% | ||||||
|  |                     \fi | ||||||
|  |                     \chaptermark{#1}% | ||||||
|  |                     \addtocontents{lof}{\protect\addvspace{10\p@}}% | ||||||
|  |                     \addtocontents{lot}{\protect\addvspace{10\p@}}% | ||||||
|  |                     \if@twocolumn | ||||||
|  |                       \@topnewpage[\@makechapterhead{#2}]% | ||||||
|  |                     \else | ||||||
|  |                       \@makechapterhead{#2}% | ||||||
|  |                       \@afterheading | ||||||
|  |                     \fi} | ||||||
|  |  | ||||||
|  | \newcommand{\RTcleardoublepage}{ | ||||||
|  | 	\clearpage\if@twoside \ifodd\c@page\else | ||||||
|  | 	\thispagestyle{empty}\hbox{}\newpage | ||||||
|  | 	\if@twocolumn\hbox{}\newpage\fi\fi\fi} | ||||||
|  |  | ||||||
|  | \let\RToldcleardoublepage\cleardoublepage | ||||||
|  | \renewcommand{\cleardoublepage}{\RTcleardoublepage} | ||||||
|  |  | ||||||
|  | % adjust margins for binding  (changed 2007-04-24 tgp) | ||||||
|  | \setlength{\oddsidemargin}{.5in} | ||||||
|  | \setlength{\evensidemargin}{0in} | ||||||
|  | \setlength{\textwidth}{6.0in} | ||||||
|  | \setlength{\textheight}{9.0in} | ||||||
|  | \setlength\topmargin{0in} | ||||||
|  | \addtolength\topmargin{-\headheight} | ||||||
|  | \addtolength\topmargin{-\headsep} | ||||||
|  |  | ||||||
|  | %\setlength{\oddsidemargin}{.6in} | ||||||
|  | %\setlength{\evensidemargin}{0in} | ||||||
|  | %\setlength{\textwidth}{5.9in} | ||||||
|  | %\setlength\topmargin{0in} | ||||||
|  | %\addtolength\headheight{2.5pt} | ||||||
|  | %\addtolength\topmargin{-\headheight} | ||||||
|  | %\addtolength\topmargin{-\headsep} | ||||||
|  | %\addtolength\textheight{1in} | ||||||
|  | %\addtolength\textheight{\headheight} | ||||||
|  | %\addtolength\textheight{\headsep} | ||||||
|  |  | ||||||
|  | \def\division#1{\gdef \@division{#1}} | ||||||
|  | \def\@division{\@latex@warning@no@line{No \noexpand\division given}} | ||||||
|  | \def\department#1{\gdef \@department{#1}} | ||||||
|  | \def\@department{\@latex@warning@no@line{No \noexpand\department given}} | ||||||
|  | \def\thedivisionof#1{\gdef \@thedivisionof{#1}} | ||||||
|  | \def\@thedivisionof{The Division of} | ||||||
|  | \def\approvedforthe#1{\gdef \@approvedforthe{#1}} | ||||||
|  | \def\@approvedforthe{Division} | ||||||
|  | \def\advisor#1{\gdef \@advisor{#1}} | ||||||
|  | \def\@advisor{\@latex@warning@no@line{No \noexpand\advisor given}} | ||||||
|  | \def\altadvisor#1{\gdef \@altadvisor{#1} \@altadvisortrue} | ||||||
|  | \global\let\@altadvisor\@empty | ||||||
|  | \newif\if@altadvisor | ||||||
|  | \@altadvisorfalse | ||||||
|  |  | ||||||
|  | \renewcommand{\contentsname}{Table of Contents} | ||||||
|  | \renewcommand{\bibname}{References} | ||||||
|  |  | ||||||
|  | \renewcommand\l@chapter[2]{% | ||||||
|  |   \ifnum \c@tocdepth >\m@ne | ||||||
|  |     \addpenalty{-\@highpenalty}% | ||||||
|  |     \vskip 1.0em \@plus\p@ | ||||||
|  |     \setlength\@tempdima{1.5em}% | ||||||
|  |     \begingroup | ||||||
|  |       \parindent \z@ \rightskip \@pnumwidth | ||||||
|  |       \parfillskip -\@pnumwidth | ||||||
|  |       \leavevmode \bfseries | ||||||
|  |       \advance\leftskip\@tempdima | ||||||
|  |       \hskip -\leftskip | ||||||
|  |       #1\nobreak\normalfont | ||||||
|  |       \leaders\hbox{$\m@th \mkern \@dotsep mu\hbox{.}\mkern \@dotsep mu$}\hfill | ||||||
|  |       \nobreak\hb@xt@\@pnumwidth{\bfseries \hss #2}\par | ||||||
|  |       \penalty\@highpenalty | ||||||
|  |     \endgroup | ||||||
|  |   \fi} | ||||||
|  |  | ||||||
|  | \newenvironment{abstract}{% | ||||||
|  |   \if@twocolumn | ||||||
|  |     \@restonecoltrue\onecolumn | ||||||
|  |   \else | ||||||
|  |     \@restonecolfalse | ||||||
|  |   \fi | ||||||
|  |   \chapter[Abstract]{} | ||||||
|  |   \begin{center} | ||||||
|  |   {\fontsize{14}{16}\selectfont \bfseries Abstract} | ||||||
|  |   \end{center} | ||||||
|  |   \fontsize{12}{14}\selectfont | ||||||
|  | }{\clearpage \if@restonecol\twocolumn\fi}% | ||||||
|  |  | ||||||
|  | \ifx\@pdfoutput\@undefined | ||||||
|  |   \newcommand{\RTpercent}{\@percentchar\space} | ||||||
|  |   \AtBeginDvi{\special{!\RTpercent Reed College LaTeX Thesis Class 2001/12/04 SN}}  | ||||||
|  |   \AtBeginDvi{\special{rawpostscript \RTpercent Reed College LaTeX Thesis Class 2001/12/04 SN}}  | ||||||
|  | \else | ||||||
|  |   \AtEndDocument{\pdfinfo{/Creator	(Reed College LaTeX Thesis Class 2001/12/04 SN)}}  | ||||||
|  | \fi | ||||||
|  |  | ||||||
|  | % I hacked the title page to all be the same font size  | ||||||
|  | % as requested by the library, BTS 2005 | ||||||
|  |  | ||||||
|  | \renewcommand{\maketitle}{% | ||||||
|  |   {\pagestyle{empty} | ||||||
|  |   \fontsize{12}{14}\selectfont | ||||||
|  |   \begin{titlepage} | ||||||
|  |   \newpage | ||||||
|  |   \let\footnotesize\small | ||||||
|  |   \let\footnoterule\relax | ||||||
|  |   \let \footnote \thanks | ||||||
|  |  | ||||||
|  |   \baselineskip = 1.4\baselineskip | ||||||
|  |   \setbox0=\hbox{of the Requirements for the Degree} | ||||||
|  |  | ||||||
|  |   \begin{center} | ||||||
|  |     \setcounter{page}{1} | ||||||
|  |     \null\vfil | ||||||
|  |     {\fontsize{12}{14}\selectfont \@title} | ||||||
|  |     \vfil | ||||||
|  |     \centerline{\hbox to \wd0 {\hbox{}\hrulefill\hbox{}}} | ||||||
|  |     \vfil | ||||||
|  |     A Thesis \\ | ||||||
|  |     Presented to \\ | ||||||
|  |     \@thedivisionof \ \@division \\ | ||||||
|  |     Reed College | ||||||
|  |     \vfil | ||||||
|  |     \centerline{\hbox to \wd0 {\hbox{}\hrulefill\hbox{}}} | ||||||
|  |     \vfil | ||||||
|  |     In Partial Fulfillment \\ | ||||||
|  |     of the Requirements for the Degree \\ | ||||||
|  |     Bachelor of Arts | ||||||
|  |     \vfil | ||||||
|  |     \centerline{\hbox to \wd0 {\hbox{}\hrulefill\hbox{}}} | ||||||
|  |     \bigskip | ||||||
|  |     \centerline{} | ||||||
|  |     \bigskip | ||||||
|  |     {\fontsize{12}{14}\selectfont \lineskip .75em | ||||||
|  |     \begin{tabular}[t]{c}% | ||||||
|  |       \@author | ||||||
|  |     \end{tabular}\par} | ||||||
|  |     \vskip 1.5em | ||||||
|  |     {\fontsize{12}{14}\selectfont \@date \par} | ||||||
|  |   \end{center}\par | ||||||
|  |   \end{titlepage} | ||||||
|  |  | ||||||
|  | %% Approved for the division page | ||||||
|  |   \cleardoublepage | ||||||
|  |   {\fontsize{12}{14} | ||||||
|  |   \setbox0=\hbox{Approved for the \@approvedforthe} | ||||||
|  |   \thispagestyle{empty} | ||||||
|  |   \null\vfil		% just below center of page | ||||||
|  |   \par\vskip 6cm	% below center, not center | ||||||
|  |   \centerline{\copy0}	% approved | ||||||
|  |   \centerline{(\@department)} %major | ||||||
|  |   \vskip 1cm		%space to sign | ||||||
|  |   \centerline{\makebox[\wd0][c]{\hrulefill} | ||||||
|  | 	\if@altadvisor \makebox[.5in]{} \makebox[\wd0][c]{\hrulefill} \fi} | ||||||
|  |   \centerline{\makebox[\wd0][c]{\@advisor} | ||||||
|  | 	\if@altadvisor \makebox[.5in]{} \makebox[\wd0][c]{\@altadvisor} \fi} | ||||||
|  |   \par\vfil\null} | ||||||
|  |   \cleardoublepage | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -288,8 +288,14 @@ class TestBlob < Test::Unit::TestCase | |||||||
|     assert_nil blob("octocat.png").language |     assert_nil blob("octocat.png").language | ||||||
|  |  | ||||||
|     # .cls disambiguation |     # .cls disambiguation | ||||||
|     assert_equal Language['OpenEdge ABL'], blob("openedge.cls").language |     # https://github.com/abevoelker/abl-email-client/blob/master/com/abevoelker/email/Email.cls | ||||||
|     assert_equal Language['TeX'], blob("latex.cls").language |     assert_equal Language['OpenEdge ABL'], blob("Email.cls").language | ||||||
|  |     # https://github.com/emcmanis/Thesis/blob/master/TeX/Thesis%20Template/reedthesis.cls | ||||||
|  |     assert_equal Language['TeX'], blob("reedthesis.cls").language | ||||||
|  |     # https://github.com/DangerMouseB/VLMessaging/blob/master/VLMMachineRouter/cApplication.cls | ||||||
|  |     assert_equal Language['Visual Basic'], blob("cApplication.cls").language | ||||||
|  |     # https://github.com/apex-commons/base/blob/master/src/classes/ArrayUtils.cls | ||||||
|  |     assert_equal Language['Apex'], blob("ArrayUtils.cls").language | ||||||
|  |  | ||||||
|     # .pl disambiguation |     # .pl disambiguation | ||||||
|     assert_equal Language['Prolog'],      blob("test-prolog.pl").language |     assert_equal Language['Prolog'],      blob("test-prolog.pl").language | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ class TestLanguage < Test::Unit::TestCase | |||||||
|  |  | ||||||
|   def test_ambiguous_extensions |   def test_ambiguous_extensions | ||||||
|     assert Language.ambiguous?('.cls') |     assert Language.ambiguous?('.cls') | ||||||
|     assert_equal Language['OpenEdge ABL'], Language.find_by_extension('cls') |     assert_equal Language['TeX'], Language.find_by_extension('cls') | ||||||
|  |  | ||||||
|     assert Language.ambiguous?('.h') |     assert Language.ambiguous?('.h') | ||||||
|     assert_equal Language['C'], Language.find_by_extension('h') |     assert_equal Language['C'], Language.find_by_extension('h') | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user