//************************************************************************************** // Filename: ConversionDialog.cp // Copyright © 1999 Tomasz Kukielka. All rights reserved. // // Description: // //************************************************************************************** // Revision History: // Wednesday, June 5, 1999 - Original //************************************************************************************** #include "ConversionDialog.h" #include "CEncodingArray.h" #include #include #include #include #include "PlistPreferences.h" extern CyclonePrefs *gPrefs; // kStandardMac = 0x0000, // kStandardUnicode = 0x0100, // kStandardISO = 0x0200, // kStandardDOS = 0x0400, // kStandardWindows = 0x0500, // kStandardOther = 0x0600, TextEncoding sStandardsArr[] = {kStandardMac, kStandardUnicode, kStandardISO, kStandardDOS, kStandardWindows, kStandardOther}; ConversionDialog::ConversionDialog(Str255 sourceName)/* : StDialogHandler(3000, inSuper)*/ { LString::CopyPStr(sourceName, mSourceName); try { InitConversionDialog(); } catch(...) { DeleteAll(); throw; } } /* ConversionDialog::ConversionDialog( LWindow* inWindow, LCommander* inSuper) : StDialogHandler(inWindow, inSuper) { mSourceName[0] = 0; try { InitConversionDialog(); } catch(...) { DeleteAll(); throw; } } */ ConversionDialog::~ConversionDialog() { DeleteAll(); } void ConversionDialog::DeleteAll() { delete mEncodingBaseArr; mEncodingBaseArr = nil; delete mEncodingVariantArr; mEncodingVariantArr = nil; delete mOutEncodingBaseArr; mOutEncodingBaseArr = nil; delete mOutEncodingVariantArr; mOutEncodingVariantArr = nil; } void ConversionDialog::InitConversionDialog() { Assert_( mDialog != nil ); LStaticText *theSText = (LStaticText *)(mDialog->FindPaneByID('Name'));Assert_(theSText); theSText->SetDescriptor(mSourceName); //in mStandardPopup = dynamic_cast(mDialog->FindPaneByID('EStd'));Assert_(mStandardPopup); mEncodingPopup = dynamic_cast(mDialog->FindPaneByID('Enco'));Assert_(mEncodingPopup); mVariantPopup = dynamic_cast(mDialog->FindPaneByID('EVar'));Assert_(mVariantPopup); //out mOutStandardPopup = dynamic_cast(mDialog->FindPaneByID('ESt1'));Assert_(mOutStandardPopup); mOutEncodingPopup = dynamic_cast(mDialog->FindPaneByID('Enc1'));Assert_(mOutEncodingPopup); mOutVariantPopup = dynamic_cast(mDialog->FindPaneByID('EVa1'));Assert_(mOutVariantPopup); //line breaks mLineBreaksPopup = dynamic_cast(mDialog->FindPaneByID('LnBr')); ValidateObject_(mLineBreaksPopup); //in LBroadcaster* theBroadcaster = dynamic_cast (mStandardPopup); if (theBroadcaster != nil) theBroadcaster->AddListener(this); theBroadcaster = dynamic_cast (mEncodingPopup); if (theBroadcaster != nil) theBroadcaster->AddListener(this); // theBroadcaster = dynamic_cast (mVariantPopup); // if (theBroadcaster != nil) // theBroadcaster->AddListener(this); //out theBroadcaster = dynamic_cast (mOutStandardPopup); if (theBroadcaster != nil) theBroadcaster->AddListener(this); theBroadcaster = dynamic_cast (mOutEncodingPopup); if (theBroadcaster != nil) theBroadcaster->AddListener(this); theBroadcaster = dynamic_cast (mLineBreaksPopup); if (theBroadcaster != nil) theBroadcaster->AddListener(this); mCurrentStandardIndx = 0; mCurrentEncodingIndx = 0; // mCurrentVariantIndx = 0; mOutCurrentStandardIndx = 0; mOutCurrentEncodingIndx = 0; mDefaultEncoding = ::ResolveDefaultTextEncoding(kTextEncodingMacRoman); mEncodingBaseArr = NEW CEncodingArray(); mEncodingVariantArr = NEW LArray( sizeof(TextEncoding), nil, true );//keep sorted - use standard long comparator mOutEncodingBaseArr = NEW CEncodingArray(); mOutEncodingVariantArr = NEW LArray( sizeof(TextEncoding), nil, true );//keep sorted - use standard long comparator // mAllPossibleDestArr = nil; MenuHandle encodingBaseMenu = ::NewMenu(1000,"\pEncodings");Assert_(encodingBaseMenu); MenuHandle encodingVariantMenu = ::NewMenu(1001,"\pVariants");Assert_(encodingVariantMenu); StopListening(); mEncodingPopup->SetMacMenuH(encodingBaseMenu);//popup takse ownership of the menu and is responsible for deleting it mVariantPopup->SetMacMenuH(encodingVariantMenu); encodingBaseMenu = ::NewMenu(1002,"\pEncodings");Assert_(encodingBaseMenu); encodingVariantMenu = ::NewMenu(1003,"\pVariants");Assert_(encodingVariantMenu); mOutEncodingPopup->SetMacMenuH(encodingBaseMenu);//popup takes ownership of the menu and is responsible for deleting it mOutVariantPopup->SetMacMenuH(encodingVariantMenu); mCurrentStandardIndx = 1; mStandardPopup->SetCurrentMenuItem(1); mOutCurrentStandardIndx = 1; mOutStandardPopup->SetCurrentMenuItem(1); mLineBreaksIndex = kLineBreakNoChange; mLineBreaksPopup->SetCurrentMenuItem(kLineBreakNoChange); if( (gPrefs->flags & kExplicitLineBreakChange) == 0 ) {//auto or no change - hide item mLineBreaksPopup->Hide(); } // RebuildEncodings(kInput); // mCurrentEncodingIndx = 1; // mEncodingPopup->SetCurrentMenuItem(1); // RebuildVariants(kInput); // mCurrentVariantIndx = 1; // mVariantPopup->SetCurrentMenuItem(1); StartListening(); // RebulidOutput(); EncodingChanged(kInput, true); EncodingChanged(kOutput, true); if( (gPrefs->flags & kExplicitLineBreakChange) != 0 ) {//only when explicit //disable PS for non-Unicode encodings MenuHandle macMenuH = mLineBreaksPopup->GetMacMenuH(); if(macMenuH != NULL) { TextEncoding enc = GetEncoding(kOutput); TextEncodingBase theBase = ::GetTextEncodingBase(enc); if( (theBase >= kStandardUnicode) && (theBase < kStandardISO) ) {//when Unicode #if TARGET_API_MAC_CARBON ::EnableMenuItem( macMenuH, 5 ); #else ::EnableItem( macMenuH, 5 ); #endif } else {//not unicode if( mLineBreaksPopup->GetCurrentMenuItem() == kLineBreakUnicode) { mLineBreaksPopup->SetCurrentMenuItem(kLineBreakNoChange); } #if TARGET_API_MAC_CARBON ::DisableMenuItem( macMenuH, 5 ); #else ::DisableItem( macMenuH, 5 ); #endif } } } } Boolean ConversionDialog::ShowDialog() { Boolean isAccepted = false; Assert_( mDialog != nil ); mDialog->Show(); while ( true ) { MessageT theMessage = DoDialog(); if ( theMessage == msg_Cancel ) { isAccepted = false; break; } else if ( theMessage == msg_OK) { isAccepted = true; break; } } return isAccepted; } void ConversionDialog::ListenToMessage( MessageT inMessage, void* /* ioParam */) { mMessage = inMessage; // Store message. DoDialog() will return this value. switch(mMessage) { case 'EStd': { StandardChanged(kInput); // RebulidOutput(); } break; case 'Enco': { EncodingChanged(kInput); // RebulidOutput(); } break; /* case 'EVar': { SInt32 newValue = mVariantPopup->GetValue(); if(newValue != mCurrentVariantIndx) { mCurrentVariantIndx = newValue; RebulidOutput(); } } break; */ case 'ESt1': { StandardChanged(kOutput); } break; case 'Enc1': { EncodingChanged(kOutput); } break; case 'LnBr': { mLineBreaksIndex = mLineBreaksPopup->GetValue(); } break; } } TextEncoding ConversionDialog::GetEncoding(UInt32 inSelector) { LArray *array = (inSelector == kInput) ? mEncodingVariantArr : mOutEncodingVariantArr; LPopupButton *popup = (inSelector == kInput) ? mVariantPopup : mOutVariantPopup; TextEncoding outEnc; array->FetchItemAt( popup->GetValue(), &outEnc); return outEnc; } void ConversionDialog::StandardChanged(UInt32 inSelector) { LPopupButton *popup = (inSelector == kInput) ? mStandardPopup : mOutStandardPopup; SInt32 *currIndexPtr = (inSelector == kInput) ? &mCurrentStandardIndx : &mOutCurrentStandardIndx; SInt32 newValue = popup->GetValue(); if(newValue != *currIndexPtr) { *currIndexPtr = newValue; EncodingChanged(inSelector, true); if( (inSelector == kOutput) && ((gPrefs->flags & kExplicitLineBreakChange) != 0) ) { MenuHandle macMenuH = mLineBreaksPopup->GetMacMenuH(); if(macMenuH != NULL) { TextEncoding enc = GetEncoding(kOutput); TextEncodingBase theBase = ::GetTextEncodingBase(enc); if( (theBase >= kStandardUnicode) && (theBase < kStandardISO) ) { #if TARGET_API_MAC_CARBON ::EnableMenuItem( macMenuH, 5 ); #else ::EnableItem( macMenuH, 5 ); #endif } else { if( mLineBreaksPopup->GetCurrentMenuItem() == kLineBreakUnicode) { mLineBreaksPopup->SetCurrentMenuItem(kLineBreakNoChange); } #if TARGET_API_MAC_CARBON ::DisableMenuItem( macMenuH, 5 ); #else ::DisableItem( macMenuH, 5 ); #endif } } } } } void ConversionDialog::EncodingChanged(UInt32 inSelector, Boolean inForceRebulid) { CEncodingArray *baseArr = (inSelector == kInput) ? mEncodingBaseArr : mOutEncodingBaseArr; LArray *varArr = (inSelector == kInput) ? mEncodingVariantArr : mOutEncodingVariantArr; LPopupButton *encPop = (inSelector == kInput) ? mEncodingPopup : mOutEncodingPopup; LPopupButton *varPop = (inSelector == kInput) ? mVariantPopup : mOutVariantPopup; SInt32 *currIndexPtr = (inSelector == kInput) ? &mCurrentEncodingIndx : &mOutCurrentEncodingIndx; ArrayIndexT index = LArray::index_Bad; if(inForceRebulid) { RebuildEncodings(inSelector); ResolveDefaultEncoding(inSelector, 1); index = baseArr->FetchIndexByEncodingBase( mDefaultEncoding );//we are interested in base only if(index == LArray::index_Bad) index = 1;//if something goes wrong - set to the first item *currIndexPtr = index;//prevent variants rebuild encPop->StopBroadcasting(); encPop->SetCurrentMenuItem(index); encPop->StartBroadcasting(); encPop->Refresh(); RebuildVariants(inSelector); } else { SInt32 newValue = encPop->GetValue(); if(newValue != *currIndexPtr) { *currIndexPtr = newValue; RebuildVariants(inSelector); ResolveDefaultEncoding(inSelector, *currIndexPtr ); } } index = varArr->FetchIndexOf( &mDefaultEncoding ); if(index == LArray::index_Bad) index = 1;//if something goes wrong - set to the first item varPop->StopBroadcasting(); varPop->SetCurrentMenuItem(index); varPop->StartBroadcasting(); varPop->Refresh(); } void ConversionDialog::RebuildEncodings(UInt32 inSelector) { CEncodingArray *baseArr = (inSelector == kInput) ? mEncodingBaseArr : mOutEncodingBaseArr; LPopupButton *encPop = (inSelector == kInput) ? mEncodingPopup : mOutEncodingPopup; SInt32 *currStdIndexPtr = (inSelector == kInput) ? &mCurrentStandardIndx : &mOutCurrentStandardIndx; // LArray *allEncArray = (inSelector == kInput) ? CConverter::sAllTextEncodingsArr : mAllPossibleDestArr; LArray *allEncArray = CConverter::sAllTextEncodingsArr; if(allEncArray == nil) return; UInt32 start, end; CConverter::GetSpecifiedEncodingsRange(allEncArray, sStandardsArr[*currStdIndexPtr - 1], start, end); if( (start == 0) && (end == 0) ) return; //delete from array if( baseArr->GetCount() > 0 ) baseArr->RemoveAllItemsAfter(0); //delete from menu MenuHandle theMenuH = encPop->GetMacMenuH(); short itemCnt = ::CountMenuItems( theMenuH ); if(itemCnt > 0) { for(short i= itemCnt; i > 0 ; i--) ::DeleteMenuItem( theMenuH, i ); } TextEncodingBase previousEncodingBase = 0xFFFFFFFF;//make sure the first item is different TextEncodingBase currEncBase; TextEncoding textEnc; UInt32 j = 1; for(UInt32 i = start; i<=end; i++)//take encodings from the range and put them one by one into array { //but skip encodings with the same base (take first encoding in the block) allEncArray->FetchItemAt( i, &textEnc); currEncBase = ::GetTextEncodingBase(textEnc); if( currEncBase != previousEncodingBase ) { //add to array previousEncodingBase = currEncBase; ArrayIndexT currIndx = baseArr->AddEncoding( textEnc );//must add real encoding, not base only //baseArr->AddItem( &textEnc ); } } for(UInt32 j = 1; j <= baseArr->GetCount(); j++) { //add to menu //add to menu ::MacInsertMenuItem(theMenuH, Str_Dummy, j-1); Str255 encodingName; if( baseArr->FetchEncNameAt(j, encodingName) ) { ::SetMenuItemText(theMenuH, (SInt16) j, encodingName ); } else { SignalStringLiteral_( "Could not fetch encoding name" ); } } encPop->StopBroadcasting(); encPop->SetMaxValue( ::CountMenuItems( theMenuH ) ); encPop->StartBroadcasting(); } void ConversionDialog::RebuildVariants(UInt32 inSelector) { CEncodingArray *baseArr = (inSelector == kInput) ? mEncodingBaseArr : mOutEncodingBaseArr; LArray *varArr = (inSelector == kInput) ? mEncodingVariantArr : mOutEncodingVariantArr; LPopupButton *encPop = (inSelector == kInput) ? mEncodingPopup : mOutEncodingPopup; LPopupButton *varPop = (inSelector == kInput) ? mVariantPopup : mOutVariantPopup; // SInt32 *currEncIndexPtr = (inSelector == kInput) ? &mCurrentEncodingIndx : &mOutCurrentEncodingIndx; // LArray *allEncArray = (inSelector == kInput) ? CConverter::sAllTextEncodingsArr : mAllPossibleDestArr; LArray *allEncArray = CConverter::sAllTextEncodingsArr; if(allEncArray == nil) return; //delete from array if( varArr->GetCount() > 0 ) varArr->RemoveAllItemsAfter(0); //delete from menu MenuHandle theMenuH = varPop->GetMacMenuH(); short itemCnt = ::CountMenuItems( theMenuH ); if(itemCnt > 0) { for(short i= itemCnt; i > 0 ; i--) ::DeleteMenuItem( theMenuH, i ); } SInt32 indx = encPop->GetValue(); TextEncoding textEnc; //baseArr->FetchItemAt( indx, &textEnc); if( ! baseArr->FetchEncValueAt(indx, &textEnc) ) return; ArrayIndexT foundEncIndx = allEncArray->FetchIndexOf( &textEnc ); Assert_(foundEncIndx != LArray::index_Bad); TextEncodingBase theBase = ::GetTextEncodingBase( textEnc ); //search down and up indx = foundEncIndx; do { varArr->AddItem( &textEnc ); indx--; allEncArray->FetchItemAt( indx, &textEnc); } while( (indx > 0) && (::GetTextEncodingBase( textEnc ) == theBase) ); indx = foundEncIndx + 1; allEncArray->FetchItemAt( indx, &textEnc); UInt32 allEncoCount = allEncArray->GetCount(); while( (indx <= allEncoCount) && (::GetTextEncodingBase( textEnc ) == theBase) ) { varArr->AddItem( &textEnc ); indx++; allEncArray->FetchItemAt( indx, &textEnc); } //add to menu for(UInt32 j = 1; j <= varArr->GetCount(); j++) { ::MacInsertMenuItem(theMenuH, Str_Dummy, j-1); Str255 variantName, formatName; TextEncoding currEncoding = *(TextEncoding*)(varArr->GetItemPtr(j)); CConverter::GetEncodingName( currEncoding, kTextEncodingFormatName, formatName ); CConverter::GetEncodingName( currEncoding, kTextEncodingVariantName, variantName ); LStringRef theStr( sizeof(Str255), formatName); if(formatName[0] != 0 && variantName[0] != 0) theStr += ' '; theStr += variantName; if(formatName[0] == 0) { TextEncodingVariant theVar = ::GetTextEncodingVariant( currEncoding ); if(theVar == kTextEncodingDefaultVariant) ::GetIndString(formatName, rMiscStrings, 18); else theStr = (SInt32) j;//assign number } ::SetMenuItemText(theMenuH, (SInt16) j, formatName ); } short itemsCount = ::CountMenuItems( theMenuH ); varPop->StopBroadcasting(); varPop->SetMaxValue( itemsCount ); varPop->StartBroadcasting(); if(itemsCount < 2 ) varPop->Disable(); else varPop->Enable(); } void ConversionDialog::ResolveDefaultEncoding(UInt32 inSelector, ArrayIndexT index) { CEncodingArray *baseArr = (inSelector == kInput) ? mEncodingBaseArr : mOutEncodingBaseArr; TextEncoding textEnc; //baseArr->FetchItemAt( index, &textEnc); if( ! baseArr->FetchEncValueAt(index, &textEnc) ) return; TextEncodingBase currEncBase = ::GetTextEncodingBase(textEnc); if( (currEncBase >= kStandardUnicode) && (currEncBase < kStandardISO) )//special case for Unicode to make it default correctly mDefaultEncoding = ::ResolveDefaultTextEncoding( kTextEncodingUnicodeDefault ); else mDefaultEncoding = ::ResolveDefaultTextEncoding( currEncBase ); } void ConversionDialog::SetDefaultEncoding(UInt32 inSelector, TextEncoding textEnc) { CEncodingArray *baseArr = (inSelector == kInput) ? mEncodingBaseArr : mOutEncodingBaseArr; LArray *varArr = (inSelector == kInput) ? mEncodingVariantArr : mOutEncodingVariantArr; LPopupButton *stdPop = (inSelector == kInput) ? mStandardPopup : mOutStandardPopup; LPopupButton *encPop = (inSelector == kInput) ? mEncodingPopup : mOutEncodingPopup; LPopupButton *varPop = (inSelector == kInput) ? mVariantPopup : mOutVariantPopup; //resolve default values if any TextEncoding resolvedEnc; if( (::GetTextEncodingVariant( textEnc ) == kTextEncodingDefaultVariant) || (::GetTextEncodingFormat( textEnc ) == kTextEncodingDefaultFormat)) resolvedEnc = ::ResolveDefaultTextEncoding( textEnc ); else resolvedEnc = textEnc; //check if we have to change standard to set default: TextEncodingBase theBase = ::GetTextEncodingBase(resolvedEnc); ArrayIndexT newIndex = 0; if(theBase >= kStandardMac && theBase < kStandardUnicode) newIndex = 1; else if(theBase >= kStandardUnicode && theBase < kStandardISO) newIndex = 2; else if(theBase >= kStandardISO && theBase < kStandardDOS) newIndex = 3; else if(theBase >= kStandardDOS && theBase < kStandardWindows) newIndex = 4; else if(theBase >= kStandardWindows && theBase < kStandardOther) newIndex = 5; else if(theBase >= kStandardOther && theBase < 0xFFFF) newIndex = 6; if(newIndex == 0)//wrong value - return without changing anything return; stdPop->SetCurrentMenuItem(newIndex);//this triggers StandardChanged if is changes //now we assume that standard is set and encodigs are rebuilt - now set the encoding newIndex = baseArr->FetchIndexByEncodingBase( resolvedEnc ); if(newIndex != LArray::index_Bad) { encPop->SetCurrentMenuItem(newIndex);//this triggers EncodingChanged //now we assume that te encoding is changed and variants are rebuilt newIndex = varArr->FetchIndexOf( &resolvedEnc ); if(newIndex != LArray::index_Bad) varPop->SetCurrentMenuItem(newIndex); } } void ConversionDialog::SetLineBreak(UInt16 inLineBreaksIndex) { if(inLineBreaksIndex == kLineBreakAutoChange) inLineBreaksIndex = kLineBreakNoChange; if( (gPrefs->flags & kExplicitLineBreakChange) != 0 ) {//explicit breaks if( inLineBreaksIndex == kLineBreakUnicode ) { TextEncoding enc = GetEncoding(kOutput); TextEncodingBase theBase = ::GetTextEncodingBase(enc); if( (theBase < kStandardUnicode) || (theBase >= kStandardISO) )//not unicode inLineBreaksIndex = kLineBreakNoChange; } mLineBreaksPopup->SetCurrentMenuItem(inLineBreaksIndex);//ListenToMessage will update our internal value } else { mLineBreaksPopup->SetCurrentMenuItem(kLineBreakNoChange);//when no line break or automatic line break } } UInt16 ConversionDialog::GetLineBreak() { if( (gPrefs->flags & kAutoChangeLineBreaks) != 0 ) return kLineBreakAutoChange; return (UInt16)mLineBreaksIndex; }