output file "Password Generator" include "Tlbx GameplayKit.incl" begin enum _mApplication _mFile _mEdit end enum begin enum 1 _iSeparator _iPreferences end enum begin enum _iCreate _iSeparator2 _iSave _iPrint _iSeparator4 _iClose end enum _window = 1 begin enum output 1 _passwordScroll _passwordView _offscreenPrintView _optionsHelp _checkOmitIs _checkOmitOs _checkOmitSs _checkOmit2s _charactersLongLabel _passwordLengthField _pwAmountLabel _pwAmountField _seedLabel _seedField _helpBtn _bottomLine _saveBtn _printBtn _createPasswordsBtn end enum _helpPopover = 2 begin enum 1 _popoverLabel end enum _savePanel = 1 _pwLenAlert = 2 void local fn BuildMenus // application menu _mApplication, _iSeparator menu _mApplication, _iPreferences,, @"Preferences…", @"," // file menu _mFile, -1,, @"File" menu _mFile, _iCreate,, @"Create passwords", @"p" menu _mFile, _iSeparator2 menu _mFile, _iSave,, @"Save", @"s" menu _mFile, _iPrint,, @"Print", @"p" menu _mFile, _iSeparator4 menu _mFile, _iClose,, @"Close", @"w" MenuItemSetAction( _mFile, _iClose, @"performClose:" ) editmenu _mEdit end fn void local fn BuildWindow long tag CGRect r = fn CGRectMake( 0, 0, 672, 460 ) window _window, @"Rosetta Code Password Generator", r//, NSWindowStyleMaskTitled + NSWindowStyleMaskClosable + NSWindowStyleMaskMiniaturizable WindowSetContentMinSize( _window, fn CGSizeMake(310,386) ) r = fn CGRectMake( 20, 73, 515, 370 ) scrollview _passwordScroll, r, NSLineBorder,,_window ViewSetAutoresizingMask( _passwordScroll, NSViewWidthSizable + NSViewHeightSizable ) textview _passwordView, r, _passwordScroll,, _window TextViewSetTextContainerInset( _passwordView, fn CGSizeMake( 10, 15 ) ) TextSetFontWithName( _passwordView, @"Menlo", 13.0 ) r = fn CGRectMake( -600, -600, 450, 405 ) textview _offscreenPrintView, r,,, _window TextSetFontWithName( _offscreenPrintView, @"Menlo", 13.0 ) TextSetColor( _offscreenPrintView, fn ColorBlack ) TextViewSetBackgroundColor( _offscreenPrintView, fn ColorWhite ) r = fn CGRectMake( 547, 424, 60, 16 ) textlabel _optionsHelp, @"Exclude:", r, _window r = fn CGRectMake( 607, 425, 41, 14 ) button _checkOmitIs, YES, NSControlStateValueOff, @"Il1", r, NSButtonTypeSwitch ViewSetToolTip( _checkOmitIs, @"Omit similar characters I, l and 1." ) r = fn CGRectOffset( r, 0, -24 ) button _checkOmitOs, YES ,NSControlStateValueOff, @"O0", r, NSButtonTypeSwitch ViewSetToolTip( _checkOmitOs, @"Omit similar characters O and 0." ) r = fn CGRectOffset( r, 0, -24 ) button _checkOmitSs, YES, NSControlStateValueOff, @"5S", r, NSButtonTypeSwitch ViewSetToolTip( _checkOmitSs, @"Omit similar characters 5 and S." ) r = fn CGRectOffset( r, 0, -24 ) button _checkOmit2s, YES, NSControlStateValueOff, @"2Z", r, NSButtonTypeSwitch ViewSetToolTip( _checkOmit2s, @"Omit similar characters 2 and Z." ) r = fn CGRectMake( 549, 322, 103, 16 ) textlabel _charactersLongLabel, @"Chars (4-50)", r, _window r = fn CGRectMake( 549, 298, 103, 21 ) textfield _passwordLengthField, YES, @"25", r,_window TextFieldSetBordered( _passwordLengthField, YES ) ControlSetAlignment(_passwordLengthField, NSTextAlignmentCenter ) ControlSetFormat( _passwordLengthField, @"0123456789", YES, 2, 0 ) ViewSetToolTip( _passwordLengthField, @"Set password length from 4 to 50." ) r = fn CGRectMake( 549, 263, 103, 16 ) textlabel _pwAmountLabel, @"Passwords:", r, _window r = fn CGRectMake( 549, 240, 103, 21 ) textfield _pwAmountField, YES, @"100", r,_window TextFieldSetBordered( _pwAmountField, YES ) ControlSetAlignment( _pwAmountField, NSTextAlignmentCenter ) ControlSetFormat( _pwAmountField, @"0123456789", YES, 4, 0 ) ViewSetToolTip( _pwAmountField, @"Enter number of passwords to generate." ) r = fn CGRectMake( 549, 205, 103, 16 ) textlabel _seedLabel, @"Seed value:", r, _window r = fn CGRectMake( 549, 182, 103, 21 ) textfield _seedField, YES, , r,_window TextFieldSetBordered( _seedField, YES ) ControlSetAlignment(_seedField, NSTextAlignmentCenter ) ControlSetFormat( _seedField, @"0123456789", YES, 6, 0 ) ViewSetToolTip( _seedField, @"Enter optional random seed number." ) for tag = _optionsHelp to _seedField ViewSetAutoresizingMask( tag, NSViewMinXMargin + NSViewMinYMargin ) next r = fn CGRectMake( 631, 70, 25, 25 ) button _helpBtn, YES,,, r, NSButtonTypeMomentaryLight, NSBezelStyleHelpButton, _window ViewSetToolTip( _helpBtn, @"Click for application help instructions." ) ViewSetAutoresizingMask( _helpBtn, NSViewMinXMargin + NSViewMaxYMargin ) r = fn CGRectMake( 20, 55, 632, 5 ) box _bottomline,, r, NSBoxSeparator ViewSetAutoresizingMask( _bottomline, NSViewWidthSizable + NSViewMaxYMargin ) r = fn CGRectMake( 20, 15, 62, 32 ) button _printBtn, YES, , @"Print…", r, NSButtonTypeMomentaryLight, NSBezelStyleRegularSquare, _window ViewSetAutoresizingMask( _printBtn, NSViewMaxXMargin + NSViewMaxYMargin ) r = fn CGRectMake( 91, 15, 62, 32 ) button _saveBtn, YES, , @"Save…", r, NSButtonTypeMomentaryLight, NSBezelStyleRegularSquare, _window ViewSetAutoresizingMask( _saveBtn, NSViewMaxXMargin + NSViewMaxYMargin ) r = fn CGRectMake( 522, 15, 131, 32 ) button _createPasswordsBtn, YES, , @"Create passwords", r, NSButtonTypeMomentaryLight, NSBezelStyleRegularSquare, _window ViewSetAutoresizingMask( _createPasswordsBtn, NSViewMinXMargin + NSViewMaxYMargin ) end fn void local fn BuildPopover CFStringRef helpText = @"This application generates randomized passwords from 4 to 50 characters in length. " helpText = fn StringByAppendingString( helpText, @"Theoretically, the number generated is limited only by system memory.\n\n" ) helpText = fn StringByAppendingString( helpText, @"Passwords will contain at least one each of the following character types:\n" ) helpText = fn StringByAppendingString( helpText, @"\tLowercase letters\t\t: a -> z\n" ) helpText = fn StringByAppendingString( helpText, @"\tUppercase letters\t\t: A -> Z\n" ) helpText = fn StringByAppendingString( helpText, @"\tNumbers\t\t\t\t: 0 -> 9\n" ) helpText = fn StringByAppendingString( helpText, @"\tSpecial characters\t: !\"#$%&'()*+,-./:;<=>?@[]^_{|}~\n\n" ) helpText = fn StringByAppendingString( helpText, @"You can use checkboxes to exclude visually similar characters: Il1 O0 5S 2Z.\n\n" ) helpText = fn StringByAppendingString( helpText, @"This application offers two automatic levels of randomization. However you are " ) helpText = fn StringByAppendingString( helpText, @"welcome to enter a custom randomizer seed number in the box provided.\n\n" ) helpText = fn StringByAppendingString( helpText, @"Passwords can be copied to the pasteboard, saved to a text file, or printed." ) popover _helpPopover, (0,0,395,365), NSPopoverBehaviorTransient textlabel _popoverLabel, helpText, (10,10,375,345) end fn void local fn OutOfBoundsAlert CFStringRef alertStr = @"Passwords must be at least four characters long, but no more than 50 characters." alert -_pwLenAlert,, @"Password length is out of bounds", alertStr, @"Okay", YES AlertButtonSetKeyEquivalent( _pwLenAlert, 1, @"\e" ) AlertSetStyle( _pwLenAlert, NSAlertStyleWarning ) alert _pwLenAlert end fn local fn BuildPassword as CFStringRef long i CFArrayRef charArr = fn AppProperty( @"charArray" ) CFStringRef numbers = charArr[0] CFStringRef uppercase = charArr[1] CFStringRef lowercase = charArr[2] CFStringRef symbols = charArr[3] // Omit confusing letters selected by user, if any if ( fn ButtonState( _checkOmitIs ) == NSControlStateValueOn ) numbers = fn StringByReplacingOccurrencesOfString( numbers, @"1", @"" ) uppercase = fn StringByReplacingOccurrencesOfString( uppercase, @"I", @"" ) lowercase = fn StringByReplacingOccurrencesOfString( lowercase, @"l", @"" ) end if if ( fn ButtonState( _checkOmitOs ) == NSControlStateValueOn ) numbers = fn StringByReplacingOccurrencesOfString( numbers, @"0", @"" ) uppercase = fn StringByReplacingOccurrencesOfString( uppercase, @"O", @"" ) end if if( fn ButtonState( _checkOmitSs ) == NSControlStateValueOn ) numbers = fn StringByReplacingOccurrencesOfString( numbers, @"5", @"" ) uppercase = fn StringByReplacingOccurrencesOfString( uppercase, @"S", @"" ) end if if ( fn ButtonState( _checkOmit2s ) == NSControlStateValueOn ) numbers = fn StringByReplacingOccurrencesOfString( numbers, @"2", @"" ) uppercase = fn StringByReplacingOccurrencesOfString( uppercase, @"Z", @"" ) end if // Build string pool from other character sets CFStringRef allChars = fn StringWithFormat( @"%@%@%@%@", numbers, uppercase, lowercase, symbols ) // Begin construction password string with single random character from each character set randomize CFMutableStringRef pwStr = fn MutableStringWithCapacity(0) CFStringRef rndNumberChar = fn StringWithFormat( @"%c", fn StringCharacterAtindex( numbers, rnd( len( numbers ) -1 ) ) ) CFStringRef rndUCaseChar = fn StringWithFormat( @"%c", fn StringCharacterAtindex( uppercase, rnd( len( uppercase ) -1 ) ) ) CFStringRef rndLCaseChar = fn StringWithFormat( @"%c", fn StringCharacterAtindex( lowercase, rnd( len( lowercase ) -1 ) ) ) CFStringRef rndSymbolChar = fn StringWithFormat( @"%c", fn StringCharacterAtindex( symbols, rnd( len( symbols ) -1 ) ) ) // Add first four randomized characters to password string MutableStringAppendString( pwStr, fn StringWithFormat( @"%@%@%@%@", rndNumberChar, rndUCaseChar, rndLCaseChar, rndSymbolChar ) ) // Build array of characters for shuffling CFMutableArrayRef mutArr = fn MutableArrayWithCapacity(0) for i = 0 to len(allChars) - 1 unichar tempUni = fn StringCharacterAtIndex( allChars, i ) CFStringRef s = fn StringWithFormat( @"%c", tempUni ) MutableArrayInsertObjectAtIndex( mutArr, s, i ) next // Shuffle character array for randomness CFArrayRef rndStrArr = fn GKRandomSourceArrayByShufflingObjectsInArray( fn GKRandomSourceInit, mutArr ) CFStringRef rndStr = fn ArrayComponentsJoinedByString( rndStrArr, @"" ) long pwLength = fn StringIntegerValue( fn ControlStringValue( _passwordLengthField ) ) // Subtract 4 for mandatory charaacters already set rndStr = fn StringSubstringToIndex( rndStr, pwLength - 4 ) MutableStringAppendString( pwStr, rndStr ) end fn = pwStr void local fn RandomizeWithSeed CFStringRef seedStr = fn ControlStringValue( _seedField ) if ( len(seedStr) > 0 ) long seedNum = fn StringIntegerValue( seedStr ) randomize seedNum else exit fn end if end fn void local fn CreatePasswords NSInteger i CFMutableStringRef passwords = fn MutableStringWithCapacity(0) long numberNeeded = fn StringIntegerValue( fn ControlStringValue( _pwAmountField ) ) // Get length of password designated by user long pwLength = fn StringIntegerValue( fn ControlStringValue( _passwordLengthField ) ) if ( pwLength > 50 ) or ( pwLength < 4 ) fn OutOfBoundsAlert : exit fn end if fn RandomizeWithSeed for i = 1 to numberNeeded MutableStringAppendString( passwords, fn StringWithFormat( @"%4d. %@%@\n", i, fn BuildPassword, @"\n" ) ) next TextSetString( _passwordView, passwords ) end fn void local fn SaveFile savepanel -_savePanel, @"Save file...", @"public.plain-text",,,, _true SavePanelSetCanCreateDirectories( _savePanel, YES ) SavePanelSetAllowedFileTypes( _savePanel, @[@"txt"] ) SavePanelSetExtensionHidden( _savePanel, NO ) // Run savepanel; action captured in fn DoDialog savepanel _savePanel end fn void local fn SetViewText( url as CFURLRef ) CFStringRef tempStr = fn StringWithContentsOfURL( url, NSUTF8StringEncoding, NULL ) WindowSetTitleWithRepresentedURL( _window, url ) TextSetString( _passwordView, tempStr ) end fn void local fn PrintView( tag as long ) TextSetString( _offscreenPrintView, fn TextString( tag ) ) ViewPrint( _offscreenPrintView ) end fn // Build character arrays at launch and save as application property void local fn CreateCharactersDictionary CFArrayRef charArray = @[¬ @"0123456789",¬ @"ABCDEFGHIJKLMNOPQRSTUVWXYZ",¬ @"abcdefghijklmnopqrstuvwxyz",¬ @"!\"#$%&'()*+,-./:;<=>?@[]^_{|}~"] AppSetProperty( @"charArray", charArray ) end fn void local fn DoAppEvent( ev as long ) select (ev) case _appDidFinishLaunching fn CreateCharactersDictionary fn BuildMenus fn BuildPopover fn BuildWindow case _appShouldTerminateAfterLastWindowClosed AppEventSetBool(YES) end select end fn void local fn DoMenu( menuID as long, itemID as long ) select (menuID) case _mApplication select (itemID) case _iPreferences // show preferences window end select case _mFile select (itemID) case _iCreate : fn CreatePasswords case _iSave : fn SaveFile case _iPrint : fn PrintView( _passwordView ) end select end select end fn void local fn DoDialog( ev as NSInteger, tag as NSInteger, wnd as NSInteger, obj as CFTypeRef ) select ( ev ) case _btnClick select ( tag ) case _createPasswordsBtn : fn CreatePasswords case _saveBtn : fn SaveFile case _printBtn : fn PrintView( _passwordView ) case _helpBtn : PopoverShow( _helpPopover, CGRectZero, _helpBtn, CGRectMaxXEdge ) end select end select end fn on appEvent fn DoAppEvent on menu fn DoMenu on dialog fn DoDialog HandleEvents