/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /*---------------------------------------*/ #include "prefapi.h" /* */ /* Name: Logo.cpp */ /* Description: XFE_Logo component source. */ /* Author: Ramiro Estrugo */ /* */ /*----------------------------------------------------------------------*/ #include "Logo.h" #include "xpassert.h" #include "MozillaApp.h" #include "icondata.h" #include "e_kit.h" #include /* static */ Pixmap ** XFE_Logo::_small_animation_pixmaps = NULL; /* static */ fe_icon_data ** XFE_Logo::_small_animation_data = NULL; /* static */ Pixmap ** XFE_Logo::_large_animation_pixmaps = NULL; /* static */ fe_icon_data ** XFE_Logo::_large_animation_data = NULL; /* static */ Cardinal XFE_Logo::_num_animations = 0; /* static */ Cardinal * XFE_Logo::_animation_frame_counts = NULL; #define DEFAULT_ANIMATION XFE_ANIMATION_MAIN #define DEFAULT_SIZE XFE_ANIMATION_LARGE // baggage extern "C" { void fe_NetscapeCallback(Widget, XtPointer, XtPointer); }; ////////////////////////////////////////////////////////////////////////// XFE_Logo::XFE_Logo(XFE_Frame * frame, Widget parent, const char * name, int /* interval */) : XFE_Component(frame), _frame(frame), #ifdef NETSCAPE_PRIV _mozillaEasterEgg(False), #endif /* NETSCAPE_PRIV */ _type(DEFAULT_ANIMATION), _size(DEFAULT_SIZE) { XP_ASSERT( XfeIsAlive(parent) ); XP_ASSERT( name != NULL ); // Create the base widget - a tool item m_widget = XtVaCreateWidget(name, xfeLogoWidgetClass, parent, XmNtraversalOn, True, XmNhighlightThickness, 0, NULL); // Add tooltip to logo fe_AddTipStringCallback(m_widget, XFE_Logo::tipStringCallback, NULL); // Add the netscape callback XtAddCallback(m_widget, XmNactivateCallback, fe_NetscapeCallback, (XtPointer) _frame->getContext()); XtAddCallback(m_widget, XmNdisarmCallback, &XFE_Logo::logoCallback, (XtPointer) this); XtAddCallback(m_widget, XmNactivateCallback, &XFE_Logo::logoCallback, (XtPointer) this); if ( ekit_CustomAnimation() ) { _type = XFE_ANIMATION_CUSTOM; } // Initizlize the animations if they are not valid if (!XFE_Logo::animationsAreValid()) { XFE_Logo::initAnimationData(); } updatePixmaps(); installDestroyHandler(); } ////////////////////////////////////////////////////////////////////////// XFE_Logo::~XFE_Logo() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Accessors // ////////////////////////////////////////////////////////////////////////// Cardinal XFE_Logo::getCurrentFrame() { XP_ASSERT( XfeIsAlive(m_widget) ); Cardinal index; XtVaGetValues(m_widget,XmNcurrentPixmapIndex,&index,NULL); return index; } ////////////////////////////////////////////////////////////////////////// EAnimationSize XFE_Logo::getSize() { return _size; } ////////////////////////////////////////////////////////////////////////// EAnimationType XFE_Logo::getType() { return _type; } ////////////////////////////////////////////////////////////////////////// XP_Bool XFE_Logo::isRunning() { XP_ASSERT( XfeIsAlive(m_widget) ); Boolean is_running; XtVaGetValues(m_widget,XmNanimationRunning,&is_running,NULL); return is_running; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Mutators // ////////////////////////////////////////////////////////////////////////// void XFE_Logo::setCurrentFrame(Cardinal index) { XP_ASSERT( XfeIsAlive(m_widget) ); XtVaSetValues(m_widget,XmNcurrentPixmapIndex,index,NULL); } ////////////////////////////////////////////////////////////////////////// void XFE_Logo::setInterval(Cardinal interval) { XP_ASSERT( XfeIsAlive(m_widget) ); XP_ASSERT( interval > 0 ); XtVaSetValues(m_widget,XmNanimationInterval,interval,NULL); } ////////////////////////////////////////////////////////////////////////// void XFE_Logo::setSize(EAnimationSize size) { XP_ASSERT( XfeIsAlive(m_widget) ); XP_ASSERT( size >= XFE_ANIMATION_LARGE ); XP_ASSERT( size <= XFE_ANIMATION_SMALL ); if (_size == size) { return; } _size = size; updatePixmaps(); } ////////////////////////////////////////////////////////////////////////// void XFE_Logo::setType(EAnimationType type) { XP_ASSERT( XfeIsAlive(m_widget) ); XP_ASSERT( type >= 0 ); XP_ASSERT( type < XFE_ANIMATION_MAX ); #ifdef NETSCAPE_PRIV // Mozilla rules if (_mozillaEasterEgg) { _type = XFE_ANIMATION_MOZILLA; updatePixmaps(); return; } #endif /* NETSCAPE_PRIV */ if (_type == type || _type == XFE_ANIMATION_CUSTOM) { return; } _type = type; updatePixmaps(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Control methods // ////////////////////////////////////////////////////////////////////////// void XFE_Logo::reset() { XP_ASSERT( XfeIsAlive(m_widget) ); XfeLogoAnimationReset(m_widget); } ////////////////////////////////////////////////////////////////////////// void XFE_Logo::start() { XP_ASSERT( XfeIsAlive(m_widget) ); XfeLogoAnimationStart(m_widget); } ////////////////////////////////////////////////////////////////////////// void XFE_Logo::stop() { XP_ASSERT( XfeIsAlive(m_widget) ); XfeLogoAnimationStop(m_widget); #ifdef NETSCAPE_PRIV // For compass or mozilla, we want the animation to continue where it // stopped. Tell the logo widget not too reset the pixmap when its idle. if ((_type == XFE_ANIMATION_COMPASS) || (_type == XFE_ANIMATION_MOZILLA)) { XtVaSetValues(m_widget,XmNresetWhenIdle,False,NULL); } else #endif /* NETSCAPE_PRIV */ { XtVaSetValues(m_widget,XmNresetWhenIdle,True,NULL); setCurrentFrame(0); } } ////////////////////////////////////////////////////////////////////////// #ifdef NETSCAPE_PRIV // Only Jamie gets the compass, everyone else gets MOZILLA. #define JWZ 9 static String _ee_xheads[] = { "\244\256\256\244\261\244", // akkana "\245\265\254\244\261\262", // briano "\245\266\267\250\257\257", // bstell "\246\262\261\271\250\265\266\250", // converse "\247\255\272", // djw "\247\262\265\244", // dora "\247\263", // dp "\251\265\244\261\246\254\266", // francis "\256\254\261", // kin "\255\272\275", // jwz "\257\272\250\254", // lwei "\260\246\244\251\250\250", // mcafee "\265\244\247\253\244", // radha "\265\244\260\254\265\262", // ramiro "\265\253\250\266\266", // rhess "\265\262\247\267", // rodt "\266\257\244\260\260", // slamm "\266\263\250\261\246\250", // spence "\267\244\262", // tao "\267\262\266\253\262\256", // toshok "\275\255\244\261\245\244\274" // zjanbay }; static String _ee_home_urls[] = { /* * http://home.netscape.com/people/ */ "\253\267\267\263\175\162\162\253\262\260\250" "\161\261\250\267\266\246\244\263\250" "\161\246\262\260\162\263\250\262\263\257\250\162", /* * http://www.netscape.com/people/ */ "\253\267\267\263\175\162\162\272\272\272" "\161\261\250\267\266\246\244\263\250" "\161\246\262\260\162\263\250\262\263\257\250\162", /* * http://people.netscape.com/ */ "\253\267\267\263\175\162\162\263\250\262" "\263\257\250\161\261\250\267\266\246\244" "\263\250\161\246\262\260\162", }; #define _EE_NUM_XHEADS ((int) XtNumber(_ee_xheads)) static String _ee_xheads_bufs[_EE_NUM_XHEADS]; static Cardinal _ee_xheads_lengths[_EE_NUM_XHEADS]; #define _EE_NUM_HOME_URLS ((int) XtNumber(_ee_home_urls)) static String _ee_home_urls_bufs[_EE_NUM_HOME_URLS]; static Cardinal _ee_home_urls_lengths[_EE_NUM_HOME_URLS]; #define _EE_MAGIC_NUMBER 67 static Boolean _ee_first_time = True; static String _ee_about_mozilla = "\244\245\262\270\267\175\260\262\275\254\257\257\244"; static String _ee_about_mozilla_buf; ////////////////////////////////////////////////////////////////////////// static void _ee_un_obfuscate(char * s) { if (!s) return; char * p = s; while(*p) { *p -= _EE_MAGIC_NUMBER; p++; } } ////////////////////////////////////////////////////////////////////////// void XFE_Logo::easterEgg(URL_Struct * url) { // Sanity check if (!url || !url->address || !*url->address) { return; } int i; // The "first time" we allocate non static memory for all the easter // egg strings and un-obfuscate them if (_ee_first_time) { _ee_first_time = False; _ee_about_mozilla_buf = (String) XtNewString(_ee_about_mozilla); _ee_un_obfuscate(_ee_about_mozilla_buf); for(i = 0; i < _EE_NUM_XHEADS; i++) { _ee_xheads_bufs[i] = (String) XtNewString(_ee_xheads[i]); _ee_un_obfuscate(_ee_xheads_bufs[i]); _ee_xheads_lengths[i] = XP_STRLEN(_ee_xheads_bufs[i]); } for(i = 0; i < _EE_NUM_HOME_URLS; i++) { _ee_home_urls_bufs[i] = (String) XtNewString(_ee_home_urls[i]); _ee_un_obfuscate(_ee_home_urls_bufs[i]); _ee_home_urls_lengths[i] = XP_STRLEN(_ee_home_urls_bufs[i]); } } // Look for about:mozilla if (XP_STRCMP(url->address,_ee_about_mozilla_buf) == 0) { _mozillaEasterEgg = True; setType(XFE_ANIMATION_MOZILLA); return; } XP_Bool found_xheads_prefix = False; int xheads_prefix_offset = 0; i = 0; // Look for one of the xheads home url prefixes while ((i < _EE_NUM_HOME_URLS) && !found_xheads_prefix) { if (XP_STRNCMP(url->address, _ee_home_urls_bufs[i], _ee_home_urls_lengths[i]) == 0) { found_xheads_prefix = True; xheads_prefix_offset = _ee_home_urls_lengths[i]; } i++; } // Look for one of the xheads if (found_xheads_prefix) { char * possible_xhead = url->address + xheads_prefix_offset; if (possible_xhead && *possible_xhead) { // Look for jwz if (XP_STRNCMP(possible_xhead, _ee_xheads_bufs[JWZ], _ee_xheads_lengths[JWZ]) == 0) { setType(XFE_ANIMATION_COMPASS); XtVaSetValues(m_widget,XmNresetWhenIdle,False,NULL); return; } // Look for xheads for(i = 0; i < _EE_NUM_XHEADS; i++) { if (XP_STRNCMP(possible_xhead, _ee_xheads_bufs[i], _ee_xheads_lengths[i]) == 0) { setType(XFE_ANIMATION_MOZILLA); XtVaSetValues(m_widget,XmNresetWhenIdle,False,NULL); return; } } } } // Default to the 4.x animation setType(XFE_ANIMATION_XNETSCAPE4); XtVaSetValues(m_widget,XmNresetWhenIdle,True,NULL); } #endif /* NETSCAPE_PRIV */ ////////////////////////////////////////////////////////////////////////// /* static */ Pixmap * XFE_Logo::createAnimation(XFE_Frame * frame, Widget logo, fe_icon_data * animation_data, Cardinal num_frames) { XP_ASSERT( frame != NULL ); XP_ASSERT( animation_data != NULL ); XP_ASSERT( num_frames > 0 ); Cardinal i; Pixmap * pixmaps = NULL; pixmaps = new Pixmap[num_frames]; for(i = 0; i < num_frames; i++) { pixmaps[i] = XFE_Logo::createPixmap(frame,logo,&animation_data[i]); } return pixmaps; } ////////////////////////////////////////////////////////////////////////// /* static */ Pixmap XFE_Logo::createPixmap(XFE_Frame * frame, Widget logo, fe_icon_data * icon_data) { XP_ASSERT( frame != NULL ); XP_ASSERT( XfeIsAlive(logo) ); XP_ASSERT( icon_data != NULL ); fe_icon icon; icon.pixmap = 0; fe_NewMakeIcon(frame->getBaseWidget(), XfeForeground(logo), XfeBackground(logo), &icon, NULL, icon_data->width, icon_data->height, icon_data->mono_bits, icon_data->color_bits, icon_data->mask_bits, False); assert( XfePixmapGood(icon.pixmap) ); return icon.pixmap; } ////////////////////////////////////////////////////////////////////////// /* static */ XP_Bool XFE_Logo::animationsAreValid() { return (_small_animation_pixmaps && _large_animation_pixmaps && _large_animation_data && _small_animation_data && _small_animation_data); } ////////////////////////////////////////////////////////////////////////// /* static */ void XFE_Logo::initAnimationData() { assert( !XFE_Logo::animationsAreValid() ); // Allocate space for the pixmaps and data _num_animations = 4; _small_animation_pixmaps = new Pixmap * [_num_animations]; _small_animation_data = new fe_icon_data * [_num_animations]; _large_animation_pixmaps = new Pixmap * [_num_animations]; _large_animation_data = new fe_icon_data * [_num_animations]; _animation_frame_counts = new Cardinal [_num_animations]; // Initialize all the pixmaps and data Cardinal i; for (i = 0; i < _num_animations; i++) { _small_animation_pixmaps[i] = NULL; _small_animation_data[i] = NULL; _large_animation_pixmaps[i] = NULL; _large_animation_data[i] = NULL; _animation_frame_counts[i] = 0; } // Initialize the animation counts _small_animation_data [XFE_ANIMATION_MAIN] = anim_main_small; _large_animation_data [XFE_ANIMATION_MAIN] = anim_main_large; _animation_frame_counts [XFE_ANIMATION_MAIN] = fe_anim_frames[XFE_ANIMATION_MAIN*2]; #ifdef NETSCAPE_PRIV _small_animation_data [XFE_ANIMATION_COMPASS] = anim_compass_small; _large_animation_data [XFE_ANIMATION_COMPASS] = anim_compass_large; _animation_frame_counts [XFE_ANIMATION_COMPASS] = fe_anim_frames[XFE_ANIMATION_COMPASS*2]; _small_animation_data [XFE_ANIMATION_MOZILLA] = anim_mozilla_small; _large_animation_data [XFE_ANIMATION_MOZILLA] = anim_mozilla_large; _animation_frame_counts [XFE_ANIMATION_MOZILLA] = fe_anim_frames[XFE_ANIMATION_MOZILLA*2]; #endif /* NETSCAPE_PRIV */ // Set at startup by ekit_LoadCustomAnimation() if ( anim_custom_small && anim_custom_large ) { _small_animation_data [XFE_ANIMATION_CUSTOM] = anim_custom_small; _large_animation_data [XFE_ANIMATION_CUSTOM] = anim_custom_large; _animation_frame_counts [XFE_ANIMATION_CUSTOM] = fe_anim_frames[XFE_ANIMATION_CUSTOM*2]; } else { // This shouldn't happen, but just in case... _small_animation_data [XFE_ANIMATION_CUSTOM] = anim_main_small; _large_animation_data [XFE_ANIMATION_CUSTOM] = anim_main_large; _animation_frame_counts [XFE_ANIMATION_CUSTOM] = fe_anim_frames[XFE_ANIMATION_MAIN*2]; } } ////////////////////////////////////////////////////////////////////////// void XFE_Logo::updatePixmaps() { Pixmap * pixmaps = NULL; Cardinal num_pixmaps = 0; switch(_size) { case XFE_ANIMATION_LARGE: if (!_large_animation_pixmaps[_type]) { _large_animation_pixmaps[_type] = XFE_Logo::createAnimation(_frame, m_widget, _large_animation_data[_type], _animation_frame_counts[_type]); } pixmaps = _large_animation_pixmaps[_type]; num_pixmaps = _animation_frame_counts[_type]; break; case XFE_ANIMATION_SMALL: if (!_small_animation_pixmaps[_type]) { _small_animation_pixmaps[_type] = XFE_Logo::createAnimation(_frame, m_widget, _small_animation_data[_type], _animation_frame_counts[_type]); } pixmaps = _small_animation_pixmaps[_type]; num_pixmaps = _animation_frame_counts[_type]; break; } #if 1 // Set the default 'rest' pixmap XtVaSetValues(m_widget, XmNpixmap, pixmaps[0], NULL); // Skip the first pixmap which is the default 'rest' pixmap pixmaps++; num_pixmaps--; #endif // Set the animation pixmaps XtVaSetValues(m_widget, XmNanimationPixmaps, pixmaps, XmNnumAnimationPixmaps, num_pixmaps, NULL); } ////////////////////////////////////////////////////////////////////////// /* static */ void XFE_Logo::logoCallback(Widget /* w */,XtPointer clientData,XtPointer callData) { XFE_Logo * logo = (XFE_Logo *) clientData; XfeButtonCallbackStruct * cbs = (XfeButtonCallbackStruct *) callData; XP_ASSERT( logo != NULL ); if (!logo) return; switch(cbs->reason) { case XmCR_ARM: break; case XmCR_DISARM: break; } } // XFE_Logo::tipStringCallback // Checks to see if a config pref has been set to overrule the tooltip // string or documentation string. /* static */ void XFE_Logo::tipStringCallback(Widget, XtPointer closure, XtPointer call_data) { XFE_TipStringCallbackStruct* cb_info = (XFE_TipStringCallbackStruct*) call_data; char* pref; char* value; if ( !cb_info ) return; pref = ( cb_info->reason == XFE_DOCSTRING ) ? "toolbar.logo.doc_string" : ( cb_info->reason == XFE_TIPSTRING ) ? "toolbar.logo.tooltip" : (char *)NULL; if ( pref && PREF_CopyConfigString(pref, &value) == PREF_OK ) { *(cb_info->string) = value; } } ////////////////////////////////////////////////////////////////////////// XP_Bool XFE_Logo::processTraversal(XmTraversalDirection direction) { if (m_widget && XfeIsAlive(m_widget) && XmProcessTraversal(m_widget,direction)) { return True; } return False; } //////////////////////////////////////////////////////////////////////////