Changeset 7664


Ignore:
Timestamp:
Jan 11, 2009, 5:46:51 PM (12 years ago)
Author:
charles
Message:

(1.5x) updates from trunk: all of build system & libtransmission; bugfixes in daemon, cli, and gtk; sync tr_sessionInit() changes. NOTE: mac end needs to add request-list.[ch] to its libtransmissio rules

Location:
branches/1.5x
Files:
3 added
145 edited

Legend:

Unmodified
Added
Removed
  • branches/1.5x/AUTHORS

    r6969 r7664  
    66  Mitchell Livingston <livings124@transmissionbt.com>  (Mac OS X client)
    77
    8 Web Client Developers
    9   Malcom Jarvis
    10   Dave Perrett
    11   Kendall Hopkins <SoftwareElves@gmail.com>
    12   Charles Kerr
     8Project Contributors
     9  Tomas Carnecky  (Profiling, patches, and detection of sneaky bugs)
     10  John Clay  (Website maintenance and troubleshooting)
     11  Rashid Eissing  (Mac OS X Transfers preferences icon)
     12  Hugo van Heuven, madebysofa  (Main icon design)
     13  Kendall Hopkins <SoftwareElves@gmail.com>  (Web Interface)
     14  Malcolm Jarvis <mjarvis@transmissionbt.com>  (Web Interface)
     15  Rick Patrick  (Mac OS X images)
     16  Nick Pucius  (Help documentation)
     17  Jonas Rask  (Mac OS X Globe icon)
     18  Erick Turnquist <jhujhiti@adjectivism.org>  (IPv6 code, support)
     19  Maarten Van Coile  (Wiki Wrangler, troubleshooting, support)
    1320
    1421Previous Developers
    15   Eric Petit <titer@m0k.org>  (Creator)
     22  Eric Petit <titer@m0k.org>  (Project originator)
    1623  Josh Elsasser <josh@elsasser.org>  (Daemon, Backend, GTK+ client)
    1724  Bryan Varner <bryan@varnernet.com>  (BeOS client)
    18 
    19 Project Contributors
    20   John Clay (Website maintenance and troubleshooting)
    21   Hugo van Heuven, madebysofa  (Main icon design)
    22   Nick Pucius  (Help documentation)
    23   Rick Patrick  (Mac OS X images)
    24   Jonas Rask  (Mac OS X Globe icon)
    25   Rashid Eissing  (Mac OS X Transfers preferences icon)
    2625
    2726Mac OS X Translators, current release:
  • branches/1.5x/COPYING

    r6286 r7664  
    1212portions of Transmission.
    1313
    14 Copyright 2005-2008. All code is copyrighted by the respective authors.
     14Copyright 2005-2009. All code is copyrighted by the respective authors.
    1515
    1616MIT LICENSE:
  • branches/1.5x/Makefile.am

    r6926 r7664  
    11ACLOCAL_AMFLAGS = -I m4
    22
    3 if BUILD_BEOS
    4   BEOS_DIR = beos
    5 endif
    63if BUILD_CLI
    74  CLI_DIR = cli
  • branches/1.5x/README

    r7303 r7664  
    44Transmission is a fast, easy, and free BitTorrent client.
    55
    6 It runs on Mac OS X (Cocoa interface),
    7 Linux/NetBSD/FreeBSD/OpenBSD (GTK+ interface)
     6It runs on Mac OS X (Cocoa interface) and
     7Linux/NetBSD/FreeBSD/OpenBSD (GTK+ interface).
    88
    99Visit http://www.transmissionbt.com/ for more information.
  • branches/1.5x/cli/cli.c

    r7229 r7664  
    3232#include <libtransmission/bencode.h>
    3333#include <libtransmission/makemeta.h>
    34 #include <libtransmission/metainfo.h> /* tr_metainfoFree */
    3534#include <libtransmission/tr-getopt.h>
    3635#include <libtransmission/utils.h> /* tr_wait */
     
    4039#define MY_NAME "transmission-cli"
    4140
    42 static int          showInfo         = 0;
    43 static int          showScrape       = 0;
    44 static int          isPrivate        = 0;
    45 static int          verboseLevel     = 0;
    46 static int          encryptionMode   = TR_DEFAULT_ENCRYPTION;
    47 static int          peerPort         = TR_DEFAULT_PORT;
    48 static int          peerSocketTOS    = TR_DEFAULT_PEER_SOCKET_TOS;
    49 static int          blocklistEnabled = TR_DEFAULT_BLOCKLIST_ENABLED;
    50 static int          uploadLimit      = 20;
    51 static int          downloadLimit    = -1;
    52 static int          natTraversal     = TR_DEFAULT_PORT_FORWARDING_ENABLED;
    53 static int          verify           = 0;
     41static tr_bool showInfo         = 0;
     42static tr_bool showScrape       = 0;
     43static tr_bool isPrivate        = 0;
     44static tr_bool verify           = 0;
    5445static sig_atomic_t gotsig           = 0;
    5546static sig_atomic_t manualUpdate     = 0;
    5647
    5748static const char * torrentPath  = NULL;
    58 static const char * downloadDir  = NULL;
    5949static const char * finishCall   = NULL;
    6050static const char * announce     = NULL;
    61 static const char * configdir    = NULL;
    6251static const char * sourceFile   = NULL;
    6352static const char * comment      = NULL;
     
    6554static const struct tr_option options[] =
    6655{
    67     { 'a', "announce",             "Set the new torrent's announce URL",
    68       "a",  1, "<url>"     },
    69     { 'b', "blocklist",            "Enable peer blocklists",
    70       "b",  0, NULL        },
    71     { 'B', "no-blocklist",         "Disable peer blocklists",
    72       "B",  0, NULL        },
    73     { 'c', "comment",              "Set the new torrent's comment",
    74       "c",  1, "<comment>" },
    75     { 'd', "downlimit",            "Set max download speed in KB/s",
    76       "d",  1, "<speed>"   },
    77     { 'D', "no-downlimit",         "Don't limit the download speed",
    78       "D",  0, NULL        },
    79     { 910, "encryption-required",  "Encrypt all peer connections",
    80       "er", 0, NULL        },
    81     { 911, "encryption-preferred", "Prefer encrypted peer connections",
    82       "ep", 0, NULL        },
    83     { 912, "encryption-tolerated", "Prefer unencrypted peer connections",
    84       "et", 0, NULL        },
    85     { 'f', "finish",               "Run a script when the torrent finishes",
    86       "f", 1, "<script>" },
    87     { 'g', "config-dir",           "Where to find configuration files",
    88       "g", 1, "<path>" },
    89     { 'i', "info",                 "Show torrent details and exit",
    90       "i",  0, NULL        },
    91     { 'm', "portmap",              "Enable portmapping via NAT-PMP or UPnP",
    92       "m",  0, NULL        },
    93     { 'M', "no-portmap",           "Disable portmapping",
    94       "M",  0, NULL        },
    95     { 'n', "new",                  "Create a new torrent",
    96       "n", 1, "<source>" },
    97     { 'p', "port",
    98       "Port for incoming peers (Default: " TR_DEFAULT_PORT_STR ")",
    99       "p", 1, "<port>" },
    100     { 'r', "private",              "Set the new torrent's 'private' flag",
    101       "r",  0, NULL        },
    102     { 's', "scrape",               "Scrape the torrent and exit",
    103       "s",  0, NULL        },
    104     { 't', "tos",
    105       "Peer socket TOS (0 to 255, default=" TR_DEFAULT_PEER_SOCKET_TOS_STR
    106       ")",
    107       "t", 1, "<tos>" },
    108     { 'u', "uplimit",              "Set max upload speed in KB/s",
    109       "u",  1, "<speed>"   },
    110     { 'U', "no-uplimit",           "Don't limit the upload speed",
    111       "U",  0, NULL        },
    112     { 'v', "verify",               "Verify the specified torrent",
    113       "v",  0, NULL        },
    114     { 'w', "download-dir",         "Where to save downloaded data",
    115       "w",  1, "<path>"    },
    116     {   0, NULL,                   NULL,
    117         NULL, 0, NULL        }
     56    { 'a', "announce",             "Set the new torrent's announce URL", "a",  1, "<url>"     },
     57    { 'b', "blocklist",            "Enable peer blocklists", "b",  0, NULL        },
     58    { 'B', "no-blocklist",         "Disable peer blocklists", "B",  0, NULL        },
     59    { 'c', "comment",              "Set the new torrent's comment", "c",  1, "<comment>" },
     60    { 'd', "downlimit",            "Set max download speed in KB/s", "d",  1, "<speed>"   },
     61    { 'D', "no-downlimit",         "Don't limit the download speed", "D",  0, NULL        },
     62    { 910, "encryption-required",  "Encrypt all peer connections", "er", 0, NULL        },
     63    { 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", 0, NULL        },
     64    { 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", 0, NULL        },
     65    { 'f', "finish",               "Run a script when the torrent finishes", "f", 1, "<script>" },
     66    { 'g', "config-dir",           "Where to find configuration files", "g", 1, "<path>" },
     67    { 'i', "info",                 "Show torrent details and exit", "i",  0, NULL        },
     68    { 'm', "portmap",              "Enable portmapping via NAT-PMP or UPnP", "m",  0, NULL        },
     69    { 'M', "no-portmap",           "Disable portmapping", "M",  0, NULL        },
     70    { 'n', "new",                  "Create a new torrent", "n", 1, "<source>" },
     71    { 'p', "port", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "p", 1, "<port>" },
     72    { 'r', "private",              "Set the new torrent's 'private' flag", "r",  0, NULL        },
     73    { 's', "scrape",               "Scrape the torrent and exit", "s",  0, NULL        },
     74    { 't', "tos", "Peer socket TOS (0 to 255, default=" TR_DEFAULT_PEER_SOCKET_TOS_STR ")", "t", 1, "<tos>" },
     75    { 'u', "uplimit",              "Set max upload speed in KB/s", "u",  1, "<speed>"   },
     76    { 'U', "no-uplimit",           "Don't limit the upload speed", "U",  0, NULL        },
     77    { 'v', "verify",               "Verify the specified torrent", "v",  0, NULL        },
     78    { 'w', "download-dir",         "Where to save downloaded data", "w",  1, "<path>"    },
     79    { 0, NULL, NULL, NULL, 0, NULL }
    11880};
    11981
     
    12688}
    12789
    128 static int          parseCommandLine( int           argc,
    129                                       const char ** argv );
     90static int parseCommandLine( tr_benc*, int argc, const char ** argv );
    13091
    13192static void         sigHandler( int signal );
     
    303264}
    304265
     266static const char*
     267getConfigDir( int argc, const char ** argv )
     268{
     269    int c;
     270    const char * configDir = NULL;
     271    const char * optarg;
     272    const int ind = tr_optind;
     273
     274    while(( c = tr_getopt( getUsage( ), argc, argv, options, &optarg ))) {
     275        if( c == 'g' ) {
     276            configDir = optarg;
     277            break;
     278        }
     279    }
     280
     281    tr_optind = ind;
     282
     283    if( configDir == NULL )
     284        configDir = tr_getDefaultConfigDir( MY_NAME );
     285
     286    return configDir;
     287}
     288
    305289int
    306290main( int     argc,
     
    311295    tr_ctor     * ctor;
    312296    tr_torrent  * tor = NULL;
     297    tr_benc settings;
     298    const char * configDir;
    313299
    314300    printf( "Transmission %s - http://www.transmissionbt.com/\n",
     
    321307    }
    322308
    323     /* Get options */
    324     if( parseCommandLine( argc, (const char**)argv ) )
     309    /* load the defaults from config file + libtransmission defaults */
     310    tr_bencInitDict( &settings, 0 );
     311    configDir = getConfigDir( argc, (const char**)argv );
     312    tr_sessionLoadSettings( &settings, configDir, MY_NAME );
     313
     314    /* the command line overrides defaults */
     315    if( parseCommandLine( &settings, argc, (const char**)argv ) )
    325316        return EXIT_FAILURE;
    326317
    327318    /* Check the options for validity */
    328     if( !torrentPath )
    329     {
     319    if( !torrentPath ) {
    330320        fprintf( stderr, "No torrent specified!\n" );
    331321        return EXIT_FAILURE;
    332322    }
    333     if( peerPort < 1 || peerPort > 65535 )
    334     {
    335         fprintf( stderr, "Error: Port must between 1 and 65535; got %d\n",
    336                  peerPort );
    337         return EXIT_FAILURE;
    338     }
    339     if( peerSocketTOS < 0 || peerSocketTOS > 255 )
    340     {
    341         fprintf( stderr, "Error: value must between 0 and 255; got %d\n",
    342                  peerSocketTOS );
    343         return EXIT_FAILURE;
    344     }
    345323
    346324    /* don't bind the port if we're just running the CLI
    347      * to get metainfo or to create a torrent */
     325       to get metainfo or to create a torrent */
    348326    if( showInfo || showScrape || ( sourceFile != NULL ) )
    349         peerPort = -1;
    350 
    351     if( configdir == NULL )
    352         configdir = tr_getDefaultConfigDir( );
    353 
    354     /* if no download directory specified, use cwd instead */
    355     if( !downloadDir )
    356         downloadDir = tr_strdup( tr_getcwd( ) );
    357 
    358     /* Initialize libtransmission */
    359     h = tr_sessionInitFull(
    360         configdir,
    361         "cli",                            /* tag */
    362         downloadDir,                       /* where to download torrents */
    363         TR_DEFAULT_PEX_ENABLED,
    364         natTraversal,                      /* nat enabled */
    365         peerPort,
    366         encryptionMode,
    367         TR_DEFAULT_LAZY_BITFIELD_ENABLED,
    368         uploadLimit >= 0,
    369         uploadLimit,
    370         downloadLimit >= 0,
    371         downloadLimit,
    372         TR_DEFAULT_GLOBAL_PEER_LIMIT,
    373         verboseLevel + 1,                  /* messageLevel */
    374         0,                                 /* is message queueing enabled? */
    375         blocklistEnabled,
    376         peerSocketTOS,
    377         TR_DEFAULT_RPC_ENABLED,
    378         TR_DEFAULT_RPC_PORT,
    379         TR_DEFAULT_RPC_WHITELIST_ENABLED,
    380         TR_DEFAULT_RPC_WHITELIST,
    381         FALSE, "fnord", "potzrebie",
    382         TR_DEFAULT_PROXY_ENABLED,
    383         TR_DEFAULT_PROXY,
    384         TR_DEFAULT_PROXY_PORT,
    385         TR_DEFAULT_PROXY_TYPE,
    386         TR_DEFAULT_PROXY_AUTH_ENABLED,
    387         TR_DEFAULT_PROXY_USERNAME,
    388         TR_DEFAULT_PROXY_PASSWORD );
     327        tr_bencDictAddInt( &settings, TR_PREFS_KEY_PEER_PORT, -1 );
     328
     329    h = tr_sessionInit( "cli", configDir, FALSE, &settings );
    389330
    390331    if( sourceFile && *sourceFile ) /* creating a torrent */
     
    410351    tr_ctorSetMetainfoFromFile( ctor, torrentPath );
    411352    tr_ctorSetPaused( ctor, TR_FORCE, showScrape );
    412     tr_ctorSetDownloadDir( ctor, TR_FORCE, downloadDir );
    413353
    414354    if( showScrape )
     
    524464
    525465cleanup:
     466
     467    tr_sessionSaveSettings( h, configDir, &settings );
     468
    526469    printf( "\n" );
     470    tr_bencFree( &settings );
    527471    tr_sessionClose( h );
    528472    return EXIT_SUCCESS;
     
    535479***/
    536480
    537 static void
    538 showUsage( void )
    539 {
    540     tr_getopt_usage( MY_NAME, getUsage( ), options );
    541     exit( 0 );
    542 }
    543 
    544481static int
    545 numarg( const char * arg )
    546 {
    547     char *     end = NULL;
    548     const long num = strtol( arg, &end, 10 );
    549 
    550     if( *end )
    551     {
    552         fprintf( stderr, "Not a number: \"%s\"\n", arg );
    553         showUsage( );
    554     }
    555     return num;
    556 }
    557 
    558 static int
    559 parseCommandLine( int           argc,
    560                   const char ** argv )
     482parseCommandLine( tr_benc * d, int argc, const char ** argv )
    561483{
    562484    int          c;
    563485    const char * optarg;
    564486
    565     while( ( c = tr_getopt( getUsage( ), argc, argv, options, &optarg ) ) )
     487    while(( c = tr_getopt( getUsage( ), argc, argv, options, &optarg )))
    566488    {
    567489        switch( c )
     
    570492                announce = optarg; break;
    571493
    572             case 'b':
    573                 blocklistEnabled = 1; break;
    574 
    575             case 'B':
    576                 blocklistEnabled = 0; break;
    577 
    578             case 'c':
    579                 comment = optarg; break;
    580 
    581             case 'd':
    582                 downloadLimit = numarg( optarg ); break;
    583 
    584             case 'D':
    585                 downloadLimit = -1; break;
    586 
    587             case 'f':
    588                 finishCall = optarg; break;
    589 
    590             case 'g':
    591                 configdir = optarg; break;
    592 
    593             case 'i':
    594                 showInfo = 1; break;
    595 
    596             case 'm':
    597                 natTraversal = 1; break;
    598 
    599             case 'M':
    600                 natTraversal = 0; break;
    601 
    602             case 'n':
    603                 sourceFile = optarg; break;
    604 
    605             case 'p':
    606                 peerPort = numarg( optarg ); break;
    607 
    608             case 'r':
    609                 isPrivate = 1; break;
    610 
    611             case 's':
    612                 showScrape = 1; break;
    613 
    614             case 't':
    615                 peerSocketTOS = numarg( optarg ); break;
    616 
    617             case 'u':
    618                 uploadLimit = numarg( optarg ); break;
    619 
    620             case 'U':
    621                 uploadLimit = -1; break;
    622 
    623             case 'v':
    624                 verify = 1; break;
    625 
    626             case 'w':
    627                 downloadDir = optarg; break;
    628 
    629             case 910:
    630                 encryptionMode = TR_ENCRYPTION_REQUIRED; break;
    631 
    632             case 911:
    633                 encryptionMode = TR_CLEAR_PREFERRED; break;
    634 
    635             case 912:
    636                 encryptionMode = TR_ENCRYPTION_PREFERRED; break;
    637 
     494            case 'b': tr_bencDictAddInt( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, 1 );
     495                      break;
     496            case 'B': tr_bencDictAddInt( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, 0 );
     497                      break;
     498            case 'c': comment = optarg;
     499                      break;
     500            case 'd': tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED, atoi( optarg ) );
     501                      tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED_ENABLED, 1 );
     502                      break;
     503            case 'D': tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED_ENABLED, 0 );
     504                      break;
     505            case 'f': finishCall = optarg;
     506                      break;
     507            case 'g': /* handled above */
     508                      break;
     509            case 'i': showInfo = 1;
     510                      break;
     511            case 'm': tr_bencDictAddInt( d, TR_PREFS_KEY_PORT_FORWARDING, 1 );
     512                      break;
     513            case 'M': tr_bencDictAddInt( d, TR_PREFS_KEY_PORT_FORWARDING, 0 );
     514                      break;
     515            case 'n': sourceFile = optarg; break;
     516            case 'p': tr_bencDictAddInt( d, TR_PREFS_KEY_PEER_PORT, atoi( optarg ) );
     517                      break;
     518            case 'r': isPrivate = 1;
     519                      break;
     520            case 's': showScrape = 1;
     521                      break;
     522            case 't': tr_bencDictAddInt( d, TR_PREFS_KEY_PEER_SOCKET_TOS, atoi( optarg ) );
     523                      break;
     524            case 'u': tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED, atoi( optarg ) );
     525                      tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 1 );
     526                      break;
     527            case 'U': tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 0 );
     528                      break;
     529            case 'v': verify = 1;
     530                      break;
     531            case 'w': tr_bencDictAddStr( d, TR_PREFS_KEY_DOWNLOAD_DIR, optarg );
     532                      break;
     533            case 910: tr_bencDictAddInt( d, TR_PREFS_KEY_ENCRYPTION, TR_ENCRYPTION_REQUIRED );
     534                      break;
     535            case 911: tr_bencDictAddInt( d, TR_PREFS_KEY_ENCRYPTION, TR_ENCRYPTION_PREFERRED );
     536                      break;
     537            case 912: tr_bencDictAddInt( d, TR_PREFS_KEY_ENCRYPTION, TR_CLEAR_PREFERRED );
     538                      break;
    638539            case TR_OPT_UNK:
    639                 torrentPath = optarg; break;
    640 
    641             default:
    642                 return 1;
     540                      torrentPath = optarg;
     541                      break;
     542            default: return 1;
    643543        }
    644544    }
  • branches/1.5x/configure.ac

    r7494 r7664  
    44dnl         "0" for stable, supported releases
    55dnl these should be the only two lines you need to change
    6 m4_define([user_agent_prefix],[1.42])
    7 m4_define([peer_id_prefix],[-TR1420-])
    8 
    9 AC_INIT([transmission],[user_agent_prefix],[http://trac.transmissionbt.com/newticket])
     6m4_define([user_agent_prefix],[1.42+])
     7m4_define([peer_id_prefix],[-TR142Z-])
     8
     9AC_INIT([transmission],
     10        [user_agent_prefix],
     11        [http://trac.transmissionbt.com/newticket])
    1012AC_SUBST(USERAGENT_PREFIX,[user_agent_prefix])
    1113AC_SUBST(PEERID_PREFIX,[peer_id_prefix])
     
    2123  AC_DEFINE(TR_UNSTABLE, 1, [Define to 1 if this is an unstable version of Transmission])
    2224  TR_UNSTABLE=yes
     25  enable_debug=yes
     26else
     27  enable_debug=no
    2328fi
    2429AM_CONDITIONAL(TR_UNSTABLE, test "x$TR_UNSTABLE" = "xyes")
     
    4348AC_PROG_CC
    4449AC_PROG_CXX
     50AC_C_INLINE
    4551if test "x$GCC" = "xyes" ; then
    46     CFLAGS="-g -Wall -Wformat-security -W -Wmissing-prototypes -Wdeclaration-after-statement -O3 -funroll-loops"
    47     CXXFLAGS="-g -Wall -Wformat-security -W -O3 -funroll-loops"
     52    CFLAGS="-std=gnu99 -ggdb3 -Wall -Wextra -Wredundant-decls -Wpointer-arith -Wformat-security -W -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Winline -Winit-self -Wundef -Wnested-externs -Wmissing-format-attribute"
     53    CXXFLAGS="-Wall -Wformat-security -W"
    4854fi
    4955
     
    8995dnl ----------------------------------------------------------------------------
    9096dnl
     97dnl  debugging support
     98AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug],[build with debugging support]),,,)
     99if test "x$enable_debug" = "xyes" ; then
     100        CFLAGS="$CFLAGS -g -O0"
     101        CXXFLAGS="$CXXFLAGS -g -O0"
     102else
     103        CFLAGS="$CFLAGS -g -O3 -funroll-loops -DNDEBUG "
     104        CXXFLAGS="$CXXFLAGS -g -O3 -funroll-loops -DNDEBUG "
     105fi
     106
     107
     108dnl ----------------------------------------------------------------------------
     109dnl
    91110dnl  libevent fun
    92111
     
    109128                  [have_gtk=no])
    110129AC_ARG_ENABLE([gtk],
    111               AC_HELP_STRING([--enable-gtk],[build gtk client]),
     130              AS_HELP_STRING([--enable-gtk],[build gtk client]),
    112131              [want_gtk=${enableval}],
    113132              [want_gtk=${have_gtk}])
     
    174193fi
    175194
    176 AC_CHECK_HEADERS([libintl.h])
    177 IT_PROG_INTLTOOL([0.23],[no-xml])
    178 GETTEXT_PACKAGE=transmission
    179 AC_SUBST(GETTEXT_PACKAGE)
    180 AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[Gettext package])
    181 AM_GLIB_GNU_GETTEXT
    182 transmissionlocaledir='${prefix}/${DATADIRNAME}/locale'
    183 AC_SUBST(transmissionlocaledir)
    184 
     195AC_ARG_ENABLE([nls],
     196              AS_HELP_STRING([--enable-nls],[enable native language support]),,
     197              [enable_nls=yes])
     198
     199if test "x$build_gtk" = "xyes" -a  "x$enable_nls" = "xno" ; then
     200    AC_MSG_ERROR("The gtk client cannot be built without nls support.  Try adding either --enable-nls or --disable-gtk" )
     201fi
     202
     203use_nls=no
     204if test "x$enable_nls" = "xyes" ; then
     205    use_nls=yes
     206    IT_PROG_INTLTOOL([0.23],[no-xml])
     207    AC_CHECK_HEADERS([libintl.h])
     208    GETTEXT_PACKAGE=transmission
     209    AC_SUBST(GETTEXT_PACKAGE)
     210    AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[Gettext package])
     211    AM_GLIB_GNU_GETTEXT
     212    transmissionlocaledir='${prefix}/${DATADIRNAME}/locale'
     213    AC_SUBST(transmissionlocaledir)
     214fi
    185215
    186216dnl ----------------------------------------------------------------------------
     
    190220build_wx=no
    191221AC_ARG_ENABLE([wx],
    192               AC_HELP_STRING([--enable-wx],[build wxWidgets client]),
     222              AS_HELP_STRING([--enable-wx],[build wxWidgets client]),
    193223              [want_wx=${enableval}],
    194               [want_wx=maybe])
     224              [want_wx=no])
    195225if test "x$want_wx" != "xno"; then
    196226    AM_OPTIONS_WXCONFIG
     
    211241
    212242AC_CANONICAL_HOST
    213 have_beos="no"
    214243have_darwin="no"
    215244have_msw="no"
     
    230259     ;;
    231260
    232   *beos*)
    233     have_beos="yes"
    234     RELEASE=`uname -r`
    235     case $RELEASE in
    236       6.*|5.0.4) # Zeta or R5 / BONE beta 7
    237         ;;
    238       5.0*)       # R5 / net_server
    239         CPPFLAGS="$CPPFLAGS -DBEOS_NETSERVER"
    240         ;;
    241       *)
    242         AC_MSG_ERROR("Unsupported BeOS version")
    243         ;;
    244     esac
    245     GCCVER=`$CC -dumpversion`
    246     case $GCCVER in
    247       2.95.3*|3*|4*)
    248         ;;
    249       2.9*)
    250         BEOS_OLDCC=yes
    251         ;;
    252       *)
    253         AC_MSG_ERROR("Unsupported gcc version")
    254         ;;
    255     esac
    256     ;;
    257 
    258261  *darwin*)
    259262    have_darwin="yes"
     
    274277esac
    275278
    276 AC_ARG_ENABLE([beos],
    277               [AC_HELP_STRING([--enable-beos],[build OS X client])],
    278               [build_beos=${enableval}],
    279               [build_beos=${have_beos}])
    280 AM_CONDITIONAL([BUILD_BEOS],[test "x$build_beos" = "xyes"])
    281 
    282279AC_ARG_ENABLE([cli],
    283               [AC_HELP_STRING([--enable-cli],[build command-line client])],
     280              [AS_HELP_STRING([--enable-cli],[build command-line client])],
    284281              [build_cli=${enableval}],
    285282              [build_cli="yes"])
     
    287284
    288285AC_ARG_ENABLE([mac],
    289               [AC_HELP_STRING([--enable-mac],[build OS X client])],
     286              [AS_HELP_STRING([--enable-mac],[build OS X client])],
    290287              [build_mac=${enableval}],
    291288              [build_mac=${have_darwin}])
     
    293290
    294291AC_ARG_ENABLE([daemon],
    295               [AC_HELP_STRING([--enable-daemon],[build daemon])],
     292              [AS_HELP_STRING([--enable-daemon],[build daemon])],
    296293              [build_daemon=${enableval}],
    297294              [build_daemon="yes"])
     
    299296
    300297
    301 if test "x$have_beos" = "xyes"; then
    302     AC_DEFINE([HAVE_BEOS], 1)
    303 fi
    304298if test "x$have_darwin" = "xyes"; then
    305299    AC_DEFINE([HAVE_DARWIN], 1)
     
    316310AC_CONFIG_FILES([Makefile
    317311                 transmission.spec
    318                  beos/Makefile
    319312                 cli/Makefile
    320313                 daemon/Makefile
     
    340333        Source code location:       ${srcdir}
    341334        Compiler:                   ${CXX}
     335        Debugging support           ${enable_debug}
    342336        Build Command-Line client:  ${build_cli}
    343337        Build Daemon:               ${build_daemon}
    344         Build BeOS client:          ${build_beos}
    345338        Build GTK+ client:          ${build_gtk}
    346339          ... gio support:          ${use_gio}
  • branches/1.5x/daemon/daemon.c

    r7346 r7664  
    11/*
    2  * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    1717#include <string.h> /* strcmp */
    1818
     19#include <sys/types.h> /* umask*/
     20#include <sys/stat.h> /* umask*/
     21
    1922#include <fcntl.h> /* open */
    2023#include <signal.h>
    2124#include <unistd.h> /* daemon */
    2225
     26#include <event.h>
     27
    2328#include <libtransmission/transmission.h>
    2429#include <libtransmission/bencode.h>
    25 #include <libtransmission/rpcimpl.h>
    2630#include <libtransmission/tr-getopt.h>
    2731#include <libtransmission/utils.h>
     
    3236static int           closing = FALSE;
    3337static tr_session  * mySession = NULL;
    34 static char        * myConfigFilename = NULL;
    35 
    36 #define KEY_BLOCKLIST         "blocklist-enabled"
    37 #define KEY_DOWNLOAD_DIR      "download-dir"
    38 #define KEY_ENCRYPTION        "encryption"
    39 #define KEY_LAZY_BITFIELD     "lazy-bitfield-enabled"
    40 #define KEY_PEER_LIMIT        "max-peers-global"
    41 #define KEY_PEER_PORT         "peer-port"
    42 #define KEY_PORT_FORWARDING   "port-forwarding-enabled"
    43 #define KEY_PEX_ENABLED       "pex-enabled"
    44 #define KEY_AUTH_REQUIRED     "rpc-authentication-required"
    45 #define KEY_USERNAME          "rpc-username"
    46 #define KEY_PASSWORD          "rpc-password"
    47 #define KEY_WHITELIST         "rpc-whitelist"
    48 #define KEY_WHITELIST_ENABLED "rpc-whitelist-enabled"
    49 #define KEY_RPC_PORT          "rpc-port"
    50 #define KEY_DSPEED            "download-limit"
    51 #define KEY_DSPEED_ENABLED    "download-limit-enabled"
    52 #define KEY_USPEED            "upload-limit"
    53 #define KEY_USPEED_ENABLED    "upload-limit-enabled"
    54 
    55 #define CONFIG_FILE           "settings.json"
    5638
    5739/***
    5840****  Config File
    5941***/
    60 
    61 static void
    62 replaceInt( tr_benc *    dict,
    63             const char * key,
    64             int64_t      value )
    65 {
    66     tr_bencDictRemove( dict, key );
    67     tr_bencDictAddInt( dict, key, value );
    68 }
    69 
    70 static void
    71 replaceStr( tr_benc *    dict,
    72             const char * key,
    73             const char*  value )
    74 {
    75     tr_bencDictRemove( dict, key );
    76     tr_bencDictAddStr( dict, key, value );
    77 }
    78 
    79 static void
    80 saveState( tr_session * s )
    81 {
    82     int     i, n = 0;
    83     char *  strs[4];
    84 
    85     tr_benc d;
    86 
    87     if( tr_bencLoadJSONFile( myConfigFilename, &d ) )
    88         tr_bencInitDict( &d, 16 );
    89 
    90     replaceInt( &d, KEY_BLOCKLIST,       tr_blocklistIsEnabled( s ) );
    91     replaceStr( &d, KEY_DOWNLOAD_DIR,    tr_sessionGetDownloadDir( s ) );
    92     replaceInt( &d, KEY_PEER_LIMIT,      tr_sessionGetPeerLimit( s ) );
    93     replaceInt( &d, KEY_PEER_PORT,       tr_sessionGetPeerPort( s ) );
    94     replaceInt( &d, KEY_PORT_FORWARDING, tr_sessionIsPortForwardingEnabled( s ) );
    95     replaceInt( &d, KEY_PEX_ENABLED,     tr_sessionIsPexEnabled( s ) );
    96     replaceStr( &d, KEY_USERNAME,        strs[n++] = tr_sessionGetRPCUsername( s ) );
    97     replaceStr( &d, KEY_PASSWORD,        strs[n++] = tr_sessionGetRPCPassword( s ) );
    98     replaceStr( &d, KEY_WHITELIST,       strs[n++] = tr_sessionGetRPCWhitelist( s ) );
    99     replaceInt( &d, KEY_RPC_PORT,        tr_sessionGetRPCPort( s ) );
    100     replaceInt( &d, KEY_AUTH_REQUIRED,   tr_sessionIsRPCPasswordEnabled( s ) );
    101     replaceInt( &d, KEY_DSPEED,          tr_sessionGetSpeedLimit( s, TR_DOWN ) );
    102     replaceInt( &d, KEY_DSPEED_ENABLED,  tr_sessionIsSpeedLimitEnabled( s, TR_DOWN ) );
    103     replaceInt( &d, KEY_USPEED,          tr_sessionGetSpeedLimit( s, TR_UP ) );
    104     replaceInt( &d, KEY_USPEED_ENABLED,  tr_sessionIsSpeedLimitEnabled( s, TR_UP ) );
    105     replaceInt( &d, KEY_ENCRYPTION,      tr_sessionGetEncryption( s ) );
    106 
    107     tr_bencSaveJSONFile( myConfigFilename, &d );
    108     tr_bencFree( &d );
    109     tr_ninf( MY_NAME, "saved \"%s\"", myConfigFilename );
    110 
    111     for( i = 0; i < n; ++i )
    112         tr_free( strs[i] );
    113 }
    114 
    115 static void
    116 getConfigInt( tr_benc *    dict,
    117               const char * key,
    118               int *        setme,
    119               int          defaultVal )
    120 {
    121     if( *setme < 0 )
    122     {
    123         int64_t i;
    124         if( tr_bencDictFindInt( dict, key, &i ) )
    125             *setme = i;
    126         else
    127             *setme = defaultVal;
    128     }
    129 }
    130 
    131 static void
    132 getConfigStr( tr_benc *     dict,
    133               const char *  key,
    134               const char ** setme,
    135               const char *  defaultVal )
    136 {
    137     if( !*setme )
    138     {
    139         const char * s;
    140         if( tr_bencDictFindStr( dict, key, &s ) )
    141             *setme = s;
    142         else
    143             *setme = defaultVal;
    144     }
    145 }
    146 
    147 /**
    148  * @param port      port number, or -1 if not set in the command line
    149  * @param auth      TRUE, FALSE, or -1 if not set on the command line
    150  * @param blocklist TRUE, FALSE, or -1 if not set on the command line
    151  */
    152 static void
    153 session_init( const char * configDir,
    154               const char * downloadDir,
    155               int          rpcPort,
    156               const char * whitelist,
    157               int          authRequired,
    158               const char * username,
    159               const char * password,
    160               int          blocklistEnabled )
    161 {
    162     char        * mycwd;
    163     tr_benc       state, *dict = NULL;
    164     int           peerPort = -1, peers = -1;
    165     int           whitelistEnabled = -1;
    166     int           pexEnabled = -1;
    167     int           fwdEnabled = -1;
    168     int           upLimit = -1, upLimited = -1, downLimit = -1,
    169                   downLimited = -1;
    170     int           encryption = -1;
    171     int           useLazyBitfield = -1;
    172     tr_ctor *     ctor;
    173     tr_torrent ** torrents;
    174 
    175     if( !tr_bencLoadJSONFile( myConfigFilename, &state ) )
    176         dict = &state;
    177 
    178     /***
    179     ****  Decide on which values to pass into tr_sessionInitFull().
    180     ****  The command-line arguments are given precedence and
    181     ****  the state file from the previous session is used as a fallback.
    182     ****  If neither of those can be found, the TR_DEFAULT fields are used .
    183     ***/
    184 
    185     mycwd = tr_getcwd( );
    186     getConfigStr( dict, KEY_DOWNLOAD_DIR,    &downloadDir,       mycwd );
    187     getConfigInt( dict, KEY_PEX_ENABLED,     &pexEnabled,        TR_DEFAULT_PEX_ENABLED );
    188     getConfigInt( dict, KEY_PORT_FORWARDING, &fwdEnabled,        TR_DEFAULT_PORT_FORWARDING_ENABLED );
    189     getConfigInt( dict, KEY_PEER_PORT,       &peerPort,          TR_DEFAULT_PORT );
    190     getConfigInt( dict, KEY_DSPEED,          &downLimit,         100 );
    191     getConfigInt( dict, KEY_DSPEED_ENABLED,  &downLimited,       FALSE );
    192     getConfigInt( dict, KEY_USPEED,          &upLimit,           100 );
    193     getConfigInt( dict, KEY_USPEED_ENABLED,  &upLimited,         FALSE );
    194     getConfigInt( dict, KEY_LAZY_BITFIELD,   &useLazyBitfield,   TR_DEFAULT_LAZY_BITFIELD_ENABLED );
    195     getConfigInt( dict, KEY_PEER_LIMIT,      &peers,             TR_DEFAULT_GLOBAL_PEER_LIMIT );
    196     getConfigInt( dict, KEY_BLOCKLIST,       &blocklistEnabled,  TR_DEFAULT_BLOCKLIST_ENABLED );
    197     getConfigInt( dict, KEY_RPC_PORT,        &rpcPort,           TR_DEFAULT_RPC_PORT );
    198     getConfigStr( dict, KEY_WHITELIST,       &whitelist,         TR_DEFAULT_RPC_WHITELIST );
    199     getConfigInt( dict, KEY_AUTH_REQUIRED,   &authRequired,      FALSE );
    200     getConfigStr( dict, KEY_USERNAME,        &username,          NULL );
    201     getConfigStr( dict, KEY_PASSWORD,        &password,          NULL );
    202     getConfigInt( dict, KEY_ENCRYPTION,      &encryption,        TR_DEFAULT_ENCRYPTION );
    203 
    204     whitelistEnabled = whitelist && *whitelist;
    205 
    206     /***
    207     ****
    208     ***/
    209 
    210     /* start the session */
    211     mySession = tr_sessionInitFull( configDir, "daemon", downloadDir,
    212                                     pexEnabled, fwdEnabled, peerPort,
    213                                     encryption,
    214                                     useLazyBitfield,
    215                                     upLimited, upLimit,
    216                                     downLimited, downLimit,
    217                                     peers,
    218                                     TR_MSG_INF, 0,
    219                                     blocklistEnabled,
    220                                     TR_DEFAULT_PEER_SOCKET_TOS,
    221                                     TRUE, rpcPort,
    222                                     whitelistEnabled, whitelist,
    223                                     authRequired, username, password,
    224                                     TR_DEFAULT_PROXY_ENABLED,
    225                                     TR_DEFAULT_PROXY,
    226                                     TR_DEFAULT_PROXY_PORT,
    227                                     TR_DEFAULT_PROXY_TYPE,
    228                                     TR_DEFAULT_PROXY_AUTH_ENABLED,
    229                                     TR_DEFAULT_PROXY_USERNAME,
    230                                     TR_DEFAULT_PROXY_PASSWORD );
    231 
    232 
    233     if( authRequired )
    234         tr_ninf( MY_NAME, "requiring authentication" );
    235 
    236     /* load the torrents */
    237     ctor = tr_ctorNew( mySession );
    238     torrents = tr_sessionLoadTorrents( mySession, ctor, NULL );
    239     tr_free( torrents );
    240     tr_ctorFree( ctor );
    241 
    242     if( dict )
    243         tr_bencFree( &state );
    244 
    245     tr_free( mycwd );
    246 }
    24742
    24843static const char *
     
    25449           "\n"
    25550           MY_NAME " is a headless Transmission session\n"
    256                    "that can be controlled via transmission-remote or Clutch.\n"
    257                    "\n"
    258                    "Usage: " MY_NAME " [options]";
     51           "that can be controlled via transmission-remote or Clutch.\n"
     52           "\n"
     53           "Usage: " MY_NAME " [options]";
    25954}
    26055
    26156static const struct tr_option options[] =
    26257{
    263     { 'a', "allowed",
    264       "Allowed IP addresses.  (Default: " TR_DEFAULT_RPC_WHITELIST ")",       "a",
    265       1, "<list>"     },
    266     { 'b', "blocklist",    "Enable peer blocklists",
    267       "b",             0, NULL         },
    268     { 'B', "no-blocklist", "Disable peer blocklists",
    269       "B",             0, NULL         },
    270     { 'f', "foreground",   "Run in the foreground instead of daemonizing",
    271       "f",             0, NULL         },
    272     { 'g', "config-dir",   "Where to look for configuration files",
    273       "g",             1, "<path>"     },
    274     { 'p', "port",
    275       "RPC port (Default: " TR_DEFAULT_RPC_PORT_STR ")",               "p",
    276       1, "<port>"     },
    277     { 't', "auth",         "Require authentication",
    278       "t",             0, NULL         },
    279     { 'T', "no-auth",      "Don't require authentication",
    280       "T",             0, NULL         },
    281     { 'u', "username",     "Set username for authentication",
    282       "u",             1, "<username>" },
    283     { 'v', "password",     "Set password for authentication",
    284       "v",             1, "<password>" },
    285     { 'w', "download-dir", "Where to save downloaded data",
    286       "w",             1, "<path>"     },
    287     {   0, NULL,           NULL,
    288         NULL,            0, NULL         }
     58    { 'a', "allowed", "Allowed IP addresses.  (Default: " TR_DEFAULT_RPC_WHITELIST ")", "a", 1, "<list>" },
     59    { 'b', "blocklist", "Enable peer blocklists", "b", 0, NULL },
     60    { 'B', "no-blocklist", "Disable peer blocklists", "B", 0, NULL },
     61    { 'd', "dump-settings", "Dump the settings and exit", "d", 0, NULL },
     62    { 'f', "foreground", "Run in the foreground instead of daemonizing", "f", 0, NULL },
     63    { 'g', "config-dir", "Where to look for configuration files", "g", 1, "<path>" },
     64    { 'p', "port", "RPC port (Default: " TR_DEFAULT_RPC_PORT_STR ")", "p", 1, "<port>" },
     65    { 't', "auth", "Require authentication", "t", 0, NULL },
     66    { 'T', "no-auth", "Don't require authentication", "T", 0, NULL },
     67    { 'u', "username", "Set username for authentication", "u", 1, "<username>" },
     68    { 'v', "password", "Set password for authentication", "v", 1, "<password>" },
     69    { 'w', "download-dir", "Where to save downloaded data", "w", 1, "<path>" },
     70    { 'P', "peerport", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "P", 1, "<port>" },
     71    { 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", 0, NULL },
     72    { 'M', "no-portmap", "Disable portmapping", "M", 0, NULL },
     73    { 'L', "peerlimit-global", "Maximum overall number of peers (Default: " TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ")", "L", 1, "<limit>" },
     74    { 'l', "peerlimit-torrent", "Maximum number of peers per torrent (Default: " TR_DEFAULT_PEER_LIMIT_TORRENT_STR ")", "l", 1, "<limit>" },
     75    { 910, "encryption-required",  "Encrypt all peer connections", "er", 0, NULL },
     76    { 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", 0, NULL },
     77    { 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", 0, NULL },
     78    { 0, NULL, NULL, NULL, 0, NULL }
    28979};
    29080
     
    29787
    29888static void
    299 readargs( int           argc,
    300           const char ** argv,
    301           int *         nofork,
    302           const char ** configDir,
    303           const char ** downloadDir,
    304           int *         rpcPort,
    305           const char ** whitelist,
    306           int *         authRequired,
    307           const char ** username,
    308           const char ** password,
    309           int *         blocklistEnabled )
    310 {
    311     int          c;
     89gotsig( int sig UNUSED )
     90{
     91    closing = TRUE;
     92}
     93
     94#if defined(WIN32)
     95 #define USE_NO_DAEMON
     96#elif !defined(HAVE_DAEMON) || defined(__MIPSEL__) || defined(__UCLIBC__)
     97 #define USE_TR_DAEMON
     98#else
     99 #define USE_OS_DAEMON
     100#endif
     101
     102static int
     103tr_daemon( int nochdir, int noclose )
     104{
     105#if defined(USE_OS_DAEMON)
     106    return daemon( nochdir, noclose );
     107#elif defined(USE_TR_DAEMON)
     108    pid_t pid = fork( );
     109    if( pid < 0 )
     110        return -1;
     111    else if( pid > 0 )
     112        _exit( 0 );
     113    else {
     114        pid = setsid( );
     115        if( pid < 0 )
     116            return -1;
     117
     118        pid = fork( );
     119        if( pid < 0 )
     120            return -1;
     121        else if( pid > 0 )
     122            _exit( 0 );
     123        else {
     124
     125            if( !nochdir )
     126                if( chdir( "/" ) < 0 )
     127                    return -1;
     128
     129            umask( (mode_t)0 );
     130
     131            if( !noclose ) {
     132                /* send stdin, stdout, and stderr to /dev/null */
     133                int i;
     134                int fd = open( "/dev/null", O_RDWR, 0 );
     135                for( i=0; i<3; ++i ) {
     136                    if( close( i ) )
     137                        return -1;
     138                    dup2( fd, i );
     139                }
     140                close( fd );
     141            }
     142
     143            return 0;
     144        }
     145    }
     146#else /* USE_NO_DAEMON */
     147    return 0;
     148#endif
     149}
     150
     151static const char*
     152getConfigDir( int argc, const char ** argv )
     153{
     154    int c;
     155    const char * configDir = NULL;
    312156    const char * optarg;
    313 
    314     while( ( c = tr_getopt( getUsage( ), argc, argv, options, &optarg ) ) )
    315     {
    316         switch( c )
    317         {
    318             case 'a':
    319                 *whitelist = optarg; break;
    320 
    321             case 'b':
    322                 *blocklistEnabled = 1; break;
    323 
    324             case 'B':
    325                 *blocklistEnabled = 0; break;
    326 
    327             case 'f':
    328                 *nofork = 1; break;
    329 
    330             case 'g':
    331                 *configDir = optarg; break;
    332 
    333             case 'p':
    334                 *rpcPort = atoi( optarg ); break;
    335 
    336             case 't':
    337                 *authRequired = TRUE; break;
    338 
    339             case 'T':
    340                 *authRequired = FALSE; break;
    341 
    342             case 'u':
    343                 *username = optarg; break;
    344 
    345             case 'v':
    346                 *password = optarg; break;
    347 
    348             case 'w':
    349                 *downloadDir = optarg; break;
    350 
    351             default:
    352                 showUsage( ); break;
     157    const int ind = tr_optind;
     158
     159    while(( c = tr_getopt( getUsage( ), argc, argv, options, &optarg ))) {
     160        if( c == 'g' ) {
     161            configDir = optarg;
     162            break;
    353163        }
    354164    }
    355 }
    356 
    357 static void
    358 gotsig( int sig UNUSED )
    359 {
    360     closing = TRUE;
    361 }
    362 
    363 #if !defined( WIN32 )
    364 #if !defined( HAVE_DAEMON )
    365 static int
    366 daemon( int nochdir,
    367         int noclose )
    368 {
    369     switch( fork( ) )
    370     {
    371         case 0:
    372             break;
    373 
    374         case - 1:
    375             tr_nerr( MY_NAME, "Error daemonizing (fork)! %d - %s", errno,
    376                     strerror(
    377                         errno ) );
    378             return -1;
    379 
    380         default:
    381             _exit( 0 );
    382     }
    383 
    384     if( setsid( ) < 0 )
    385     {
    386         tr_nerr( MY_NAME, "Error daemonizing (setsid)! %d - %s", errno,
    387                 strerror(
    388                     errno ) );
    389         return -1;
    390     }
    391 
    392     switch( fork( ) )
    393     {
    394         case 0:
    395             break;
    396 
    397         case - 1:
    398             tr_nerr( MY_NAME, "Error daemonizing (fork2)! %d - %s", errno,
    399                     strerror(
    400                         errno ) );
    401             return -1;
    402 
    403         default:
    404             _exit( 0 );
    405     }
    406 
    407     if( !nochdir && 0 > chdir( "/" ) )
    408     {
    409         tr_nerr( MY_NAME, "Error daemonizing (chdir)! %d - %s", errno,
    410                 strerror(
    411                     errno ) );
    412         return -1;
    413     }
    414 
    415     if( !noclose )
    416     {
    417         int fd;
    418         if( ( ( fd = open( "/dev/null", O_RDONLY ) ) ) != 0 )
    419         {
    420             dup2( fd,  0 );
    421             close( fd );
    422         }
    423         if( ( ( fd = open( "/dev/null", O_WRONLY ) ) ) != 1 )
    424         {
    425             dup2( fd, 1 );
    426             close( fd );
    427         }
    428         if( ( ( fd = open( "/dev/null", O_WRONLY ) ) ) != 2 )
    429         {
    430             dup2( fd, 2 );
    431             close( fd );
    432         }
    433     }
    434 
    435     return 0;
    436 }
    437 #endif
    438 #endif
     165
     166    tr_optind = ind;
     167
     168    if( configDir == NULL )
     169        configDir = tr_getDefaultConfigDir( MY_NAME );
     170
     171    return configDir;
     172}
     173
    439174
    440175int
     
    442177      char ** argv )
    443178{
    444     int          nofork = 0;
    445     int          rpcPort = -1;
    446     int          authRequired = -1;
    447     int          blocklistEnabled = -1;
    448     char *       freeme = NULL;
     179    int c;
     180    int64_t i;
     181    const char * optarg;
     182    tr_benc settings;
     183    tr_bool foreground = FALSE;
     184    tr_bool dumpSettings = FALSE;
    449185    const char * configDir = NULL;
    450     const char * downloadDir = NULL;
    451     const char * whitelist = NULL;
    452     const char * username = NULL;
    453     const char * password = NULL;
    454186
    455187    signal( SIGINT, gotsig );
     
    461193#endif
    462194
    463     readargs( argc, (const char**)argv, &nofork, &configDir, &downloadDir,
    464               &rpcPort, &whitelist, &authRequired, &username, &password,
    465               &blocklistEnabled );
    466     if( configDir == NULL )
    467         configDir = getenv( "TRANSMISSION_HOME" );
    468     if( configDir == NULL )
    469         configDir = freeme = tr_strdup_printf( "%s-daemon",
    470                                                tr_getDefaultConfigDir( ) );
    471     myConfigFilename = tr_buildPath( configDir, CONFIG_FILE, NULL );
    472 
    473 #ifndef WIN32
    474     if( !nofork )
     195    /* load settings from defaults + config file */
     196    tr_bencInitDict( &settings, 0 );
     197    configDir = getConfigDir( argc, (const char**)argv );
     198    tr_sessionLoadSettings( &settings, configDir, MY_NAME );
     199    tr_bencDictAddInt( &settings, TR_PREFS_KEY_RPC_ENABLED, 1 );
     200
     201    /* overwrite settings from the comamndline */
     202    tr_optind = 1;
     203    while(( c = tr_getopt( getUsage(), argc, (const char**)argv, options, &optarg ))) {
     204        switch( c ) {
     205            case 'a': tr_bencDictAddStr( &settings, TR_PREFS_KEY_RPC_WHITELIST, optarg );
     206                      tr_bencDictAddInt( &settings, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, 1 );
     207                      break;
     208            case 'b': tr_bencDictAddInt( &settings, TR_PREFS_KEY_BLOCKLIST_ENABLED, 1 );
     209                      break;
     210            case 'B': tr_bencDictAddInt( &settings, TR_PREFS_KEY_BLOCKLIST_ENABLED, 0 );
     211                      break;
     212            case 'd': dumpSettings = TRUE;
     213                      break;
     214            case 'f': foreground = TRUE;
     215                      break;
     216            case 'g': /* handled above */
     217                      break;
     218            case 'p': tr_bencDictAddInt( &settings, TR_PREFS_KEY_RPC_PORT, atoi( optarg ) );
     219                      break;
     220            case 't': tr_bencDictAddInt( &settings, TR_PREFS_KEY_RPC_AUTH_REQUIRED, 1 );
     221                      break;
     222            case 'T': tr_bencDictAddInt( &settings, TR_PREFS_KEY_RPC_AUTH_REQUIRED, 0 );
     223                      break;
     224            case 'u': tr_bencDictAddStr( &settings, TR_PREFS_KEY_RPC_USERNAME, optarg );
     225                      break;
     226            case 'v': tr_bencDictAddStr( &settings, TR_PREFS_KEY_RPC_PASSWORD, optarg );
     227                      break;
     228            case 'w': tr_bencDictAddStr( &settings, TR_PREFS_KEY_DOWNLOAD_DIR, optarg );
     229                      break;
     230            case 'P': tr_bencDictAddInt( &settings, TR_PREFS_KEY_PEER_PORT, atoi( optarg ) );
     231                      break;
     232            case 'm': tr_bencDictAddInt( &settings, TR_PREFS_KEY_PORT_FORWARDING, 1 );
     233                      break;
     234            case 'M': tr_bencDictAddInt( &settings, TR_PREFS_KEY_PORT_FORWARDING, 0 );
     235                      break;
     236            case 'L': tr_bencDictAddInt( &settings, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, atoi( optarg ) );
     237                      break;
     238            case 'l': tr_bencDictAddInt( &settings, TR_PREFS_KEY_PEER_LIMIT_TORRENT, atoi( optarg ) );
     239                      break;
     240            case 910: tr_bencDictAddInt( &settings, TR_PREFS_KEY_ENCRYPTION, TR_ENCRYPTION_REQUIRED );
     241                      break;
     242            case 911: tr_bencDictAddInt( &settings, TR_PREFS_KEY_ENCRYPTION, TR_ENCRYPTION_PREFERRED );
     243                      break;
     244            case 912: tr_bencDictAddInt( &settings, TR_PREFS_KEY_ENCRYPTION, TR_CLEAR_PREFERRED );
     245                      break;
     246            default:  showUsage( );
     247                      break;
     248        }
     249    }
     250
     251    if( dumpSettings )
    475252    {
    476         if( 0 > daemon( 1, 0 ) )
    477         {
    478             fprintf( stderr, "failed to daemonize: %s\n", strerror( errno ) );
    479             exit( 1 );
    480         }
    481     }
    482 #endif
    483 
    484     session_init( configDir, downloadDir,
    485                   rpcPort, whitelist, authRequired, username, password,
    486                   blocklistEnabled );
     253        struct evbuffer * buf = tr_getBuffer( );
     254
     255        tr_bencSaveAsJSON( &settings, buf );
     256        fprintf( stderr, "%s", (char*)EVBUFFER_DATA(buf) );
     257
     258        tr_releaseBuffer( buf );
     259        return 0;
     260    }
     261
     262    if( !foreground && tr_daemon( TRUE, FALSE ) < 0 )
     263    {
     264        fprintf( stderr, "failed to daemonize: %s\n", strerror( errno ) );
     265        exit( 1 );
     266    }
     267
     268    /* start the session */
     269    mySession = tr_sessionInit( "daemon", configDir, FALSE, &settings );
     270
     271    if( tr_bencDictFindInt( &settings, TR_PREFS_KEY_RPC_AUTH_REQUIRED, &i ) && i!=0 )
     272        tr_ninf( MY_NAME, "requiring authentication" );
     273
     274    /* load the torrents */
     275    {
     276        tr_ctor * ctor = tr_ctorNew( mySession );
     277        tr_torrent ** torrents = tr_sessionLoadTorrents( mySession, ctor, NULL );
     278        tr_free( torrents );
     279        tr_ctorFree( ctor );
     280    }
    487281
    488282    while( !closing )
    489283        tr_wait( 1000 ); /* sleep one second */
    490284
    491     saveState( mySession );
     285    /* shutdown */
    492286    printf( "Closing transmission session..." );
     287    tr_sessionSaveSettings( mySession, configDir, &settings );
    493288    tr_sessionClose( mySession );
    494289    printf( " done.\n" );
    495290
    496     tr_free( freeme );
    497     tr_free( myConfigFilename );
     291    /* cleanup */
     292    tr_bencFree( &settings );
    498293    return 0;
    499294}
    500 
  • branches/1.5x/daemon/remote.c

    r7201 r7664  
    11/*
    2  * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    1616#include <string.h> /* strcmp */
    1717
     18#ifdef WIN32
     19 #include <direct.h> /* getcwd */
     20#else
     21 #include <unistd.h> /* getcwd */
     22#endif
     23
    1824#include <libevent/event.h>
    1925#include <curl/curl.h>
     
    2935#define MY_NAME "transmission-remote"
    3036#define DEFAULT_HOST "localhost"
    31 #define DEFAULT_PORT TR_DEFAULT_RPC_PORT
     37#define DEFAULT_PORT atoi(TR_DEFAULT_RPC_PORT_STR)
    3238
    3339enum { TAG_LIST, TAG_DETAILS, TAG_FILES, TAG_PEERS };
     
    5763    { 'b', "debug",                "Print debugging information",
    5864      "b",  0, NULL                  },
    59     { 'd', "downlimit",            "Set the maximum download speed in KB/s",
     65    { 'd', "downlimit",            "Set the maximum global download speed in KB/s",
    6066      "d",  1, "<speed>"             },
    61     { 'D', "no-downlimit",         "Don't limit the download speed",
     67    { 'D', "no-downlimit",         "Don't limit the global download speed",
    6268      "D",  0, NULL                  },
    6369    { 910, "encryption-required",  "Encrypt all peer connections",
     
    8490      "n",  1, "<username:password>" },
    8591    { 'p', "port",
    86       "Port for incoming peers (Default: " TR_DEFAULT_PORT_STR ")",
     92      "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")",
    8793      "p", 1, "<port>" },
    8894    { 900, "priority-high",        "Set the files' priorities as high",
     
    94100    { 'r', "remove",               "Remove the current torrent(s)",
    95101      "r",  0, NULL                  },
     102    { 'R', "remove-and-delete",    "Remove the current torrent(s) and delete local data",
     103      NULL, 0, NULL                  },
    96104    { 's', "start",                "Start the current torrent(s)",
    97105      "s",  0, NULL                  },
     
    100108    { 't', "torrent",              "Set the current torrent(s)",
    101109      "t",  1, "<torrent>"           },
    102     { 'u', "uplimit",              "Set the maximum upload speed in KB/s",
     110    { 'u', "uplimit",              "Set the maximum global upload speed in KB/s",
    103111      "u",  1, "<speed>"             },
    104     { 'U', "no-uplimit",           "Don't limit the upload speed",
     112    { 'U', "no-uplimit",           "Don't limit the global upload speed",
    105113      "U",  0, NULL                  },
    106114    { 'v', "verify",               "Verify the current torrent(s)",
     
    143151static int    debug = 0;
    144152static char * auth = NULL;
     153
     154static char*
     155tr_getcwd( void )
     156{
     157    char buf[2048];
     158    *buf = '\0';
     159#ifdef WIN32
     160    _getcwd( buf, sizeof( buf ) );
     161#else
     162    getcwd( buf, sizeof( buf ) );
     163#endif
     164    return tr_strdup( buf );
     165}
    145166
    146167static char*
     
    396417                break;
    397418
     419            case 'R':
     420                tr_bencDictAddStr( &top, "method", "torrent-remove" );
     421                addIdArg( args, id );
     422                tr_bencDictAddInt( args, "delete-local-data", 1 );
     423                break;
     424
    398425            case 's':
    399426                tr_bencDictAddStr( &top, "method", "torrent-start" );
     
    498525
    499526        if( addArg )
    500             reqs[reqCount++] = tr_bencSaveAsJSON( &top, NULL );
     527        {
     528            struct evbuffer * buf = tr_getBuffer( );
     529            reqs[reqCount++] = tr_strdup( tr_bencSaveAsJSON( &top, buf ) );
     530            tr_releaseBuffer( buf );
     531        }
     532
    501533        tr_bencFree( &top );
    502534    }
     
    688720}
    689721
     722static const char*
     723getTrackerDateStr( const time_t t, tr_bool isStopped )
     724{
     725    const char * str;
     726    switch( t ) {
     727        case 0: str = isStopped ? "None (Stopped)\n" : "None\n"; break;
     728        case 1: str = "In Progress\n"; break;
     729        default: str = ctime( &t ); break;
     730    }
     731    return str;
     732}
     733
    690734static void
    691735printDetails( tr_benc * top )
     
    706750            char         buf2[512];
    707751            int64_t      i, j, k;
     752            tr_bool      isStopped;
     753
     754            isStopped = tr_bencDictFindInt( t, "status", &i ) && (i==TR_STATUS_STOPPED);
    708755
    709756            printf( "NAME\n" );
     
    819866
    820867            printf( "TRACKER\n" );
    821             if( tr_bencDictFindInt( t, "lastAnnounceTime", &i ) && i )
    822             {
    823                 const time_t tt = i;
    824                 printf( "  Latest announce: %s", ctime( &tt ) );
    825             }
     868            if( tr_bencDictFindInt( t, "lastAnnounceTime", &i ) )
     869                printf( "  Latest announce: %s", getTrackerDateStr( (time_t)i, isStopped ) );
    826870            if( tr_bencDictFindStr( t, "announceURL", &str ) )
    827871                printf( "  Announce URL: %s\n", str );
    828             if( tr_bencDictFindStr( t, "announceResponse",
    829                                     &str ) && str && *str )
     872            if( tr_bencDictFindStr( t, "announceResponse", &str ) && str && *str )
    830873                printf( "  Announce response: %s\n", str );
    831             if( tr_bencDictFindInt( t, "nextAnnounceTime", &i ) && i )
    832             {
    833                 const time_t tt = i;
    834                 printf( "  Next announce:   %s", ctime( &tt ) );
    835             }
    836             if( tr_bencDictFindInt( t, "lastScrapeTime", &i ) && i )
    837             {
    838                 const time_t tt = i;
    839                 printf( "  Latest scrape:   %s", ctime( &tt ) );
    840             }
     874            if( tr_bencDictFindInt( t, "nextAnnounceTime", &i ) )
     875                printf( "  Next announce:   %s", getTrackerDateStr( (time_t)i, isStopped ) );
     876            if( tr_bencDictFindInt( t, "lastScrapeTime", &i ) )
     877                printf( "  Latest scrape:   %s", getTrackerDateStr( (time_t)i, isStopped ) );
    841878            if( tr_bencDictFindStr( t, "scrapeResponse", &str ) )
    842879                printf( "  Scrape response: %s\n", str );
    843             if( tr_bencDictFindInt( t, "nextScrapeTime", &i ) && i )
    844             {
    845                 const time_t tt = i;
    846                 printf( "  Next scrape:     %s", ctime( &tt ) );
    847             }
    848             if( tr_bencDictFindInt( t, "seeders", &i )
    849               && tr_bencDictFindInt( t, "leechers", &j ) )
    850                 printf(
    851                     "  Tracker knows of %" PRId64 " seeders and %" PRId64
    852                     " leechers\n", i, j );
     880            if( tr_bencDictFindInt( t, "nextScrapeTime", &i ) )
     881                printf( "  Next scrape:     %s", getTrackerDateStr( (time_t)i, isStopped ) );
     882            if( tr_bencDictFindInt( t, "seeders", &i ) && tr_bencDictFindInt( t, "leechers", &j ) )
     883                printf( "  Tracker knows of %" PRId64 " seeders and %" PRId64 " leechers\n", i, j );
    853884            if( tr_bencDictFindInt( t, "timesCompleted", &i ) )
    854                 printf(
    855                     "  Tracker has seen %" PRId64
    856                     " clients complete this torrent\n", i );
     885                printf( "  Tracker has seen %" PRId64 " clients complete this torrent\n", i );
    857886            printf( "\n" );
    858887
     
    10561085
    10571086    if( debug )
    1058         fprintf( stderr, "got response:\n--------\n%*.*s\n--------\n", 
     1087        fprintf( stderr, "got response:\n--------\n%*.*s\n--------\n",
    10591088                 (int)len, (int)len, (const char*) response );
    10601089
     
    11251154        curl_easy_setopt( curl, CURLOPT_POSTFIELDS, reqs[i] );
    11261155        if( debug )
    1127             fprintf( stderr, "posting:\n--------\n%s\n--------\n", reqs[i] ); 
     1156            fprintf( stderr, "posting:\n--------\n%s\n--------\n", reqs[i] );
    11281157        if( ( res = curl_easy_perform( curl ) ) )
    11291158            tr_nerr( MY_NAME, "(%s:%d) %s", host, port,
  • branches/1.5x/daemon/transmission-daemon.1

    r7481 r7664  
    1919.Op Fl u Ar username
    2020.Op Fl v Ar password
     21.Op Fl P Ar port
     22.Op Fl m | M
     23.Op Fl l Ar limit
     24.Op Fl L Ar limit
     25.Op Fl er | ep | et
    2126.Op Fl w Ar download-dir
    2227.Ek
     
    5055Where to look for .torrent and config files on startup.
    5156
     57.It Fl er Fl -encryption-required
     58Encrypt all peer connections.
     59.It Fl ep Fl -encryption-preferred
     60Prefer encrypted peer connections.
     61.It Fl et Fl -encryption-tolerated
     62Prefer unencrypted peer connections.
     63
    5264.It Fl h Fl -help
    5365Print command-line option descriptions.
    5466
     67.It Fl L Fl -peerlimit-global Ar limit
     68Overall peer limit. Useful on embedded systems where the default might be unsuitable. Default: 240
     69.It Fl l Fl -peerlimit-torrent Ar limit
     70Peer limit per torrent. Useful on embedded systems where the default might be unsuitable. Default: 60
     71
     72.It Fl m Fl -portmap
     73Enable portmapping via NAT-PMP or UPnP
     74.It Fl M Fl -no-portmap
     75Disable portmapping
     76
    5577.It Fl p Fl -port Ar port
    5678Port to open and listen for RPC requests on.  Default: 9091
     79
     80.It Fl P, -peerport Ar port
     81Port to listen for incoming peers on. Default: 51413
    5782
    5883.It Fl t Fl -auth
  • branches/1.5x/daemon/transmission-remote.1

    r7038 r7664  
    2929.Op Fl pn Ar files
    3030.Op Fl r
     31.Op Fl R
    3132.Op Fl s | S
    3233.Op Fl t Ar all | Ar id | Ar hash
     
    6061
    6162.It Fl d Fl -downlimit Ar limit
    62 Limit the download speed to
     63Limit the global download speed to
    6364.Ar limit
    6465kilobytes per second.
    6566
    6667.It Fl D Fl -no-downlimit
    67 Remove the download limit.
     68Remove the global download limit.
    6869
    6970.It Fl er Fl -encryption-required
     
    135136Remove the current torrent(s).  This does not delete the downloaded data.
    136137
     138.It Fl -remove-and-delete
     139Remove the current torrent(s) and delete their downloaded data.
     140
    137141.It Fl s Fl -start
    138142Start the current torrent(s)
     
    152156
    153157.It Fl u Fl -uplimit Ar limit
    154 Limit the upload speed to
     158Limit the global upload speed to
    155159.Ar limit
    156160kilobytes per second.
    157161.It Fl U Fl -no-uplimit
    158 Remove the upload limit.
     162Remove the global upload limit.
    159163
    160164.It Fl v Fl -verify
  • branches/1.5x/gtk/actions.c

    r6949 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    109109static GtkActionEntry        entries[] =
    110110{
    111     { "torrent-menu",         NULL,                           N_(
    112           "_Torrent" ),
    113       NULL,            NULL,                   NULL                    },
    114     { "view-menu",            NULL,                  N_( "_View" ),
    115       NULL,            NULL,                   NULL                    },
    116     { "sort-menu",            NULL,                  N_(
    117           "_Sort Torrents By" ),        NULL,            NULL,
    118       NULL                    },
    119     { "edit-menu",            NULL,                  N_( "_Edit" ),
    120       NULL,            NULL,                   NULL                    },
    121     { "help-menu",            NULL,                  N_( "_Help" ),
    122       NULL,            NULL,                   NULL                    },
    123     { "add-torrent-toolbar",  GTK_STOCK_ADD,         NULL,
    124       NULL,            N_( "Add a torrent" ),  G_CALLBACK( action_cb ) },
    125     { "add-torrent-menu",     GTK_STOCK_ADD,         N_( "_Add..." ),
    126       "<control>D",    N_( "Add a torrent" ),  G_CALLBACK( action_cb ) },
    127     { "start-torrent",        GTK_STOCK_MEDIA_PLAY,
    128       N_( "_Start" ), "<control>S", N_( "Start torrent" ), G_CALLBACK(
    129           action_cb ) },
    130     { "show-stats",           NULL,                  N_( "_Statistics" ),
    131       NULL,            NULL,                   G_CALLBACK( action_cb ) },
    132     { "verify-torrent",       NULL,
    133       N_( "_Verify Local Data" ), NULL, NULL, G_CALLBACK( action_cb ) },
    134     { "pause-torrent",        GTK_STOCK_MEDIA_PAUSE,
    135       N_( "_Pause" ), "<control>P", N_( "Pause torrent" ), G_CALLBACK(
    136           action_cb ) },
    137     { "remove-torrent",       GTK_STOCK_REMOVE,      NULL,
    138       "Delete",        N_( "Remove torrent" ), G_CALLBACK( action_cb ) },
    139     { "delete-torrent",       GTK_STOCK_DELETE,      N_(
    140           "_Delete Files and Remove" ), "<shift>Delete", NULL,
    141       G_CALLBACK( action_cb ) },
    142     { "new-torrent",          GTK_STOCK_NEW,         N_( "_New..." ),
    143       NULL,
    144       N_( "Create a torrent" ),
    145       G_CALLBACK( action_cb ) },
    146     { "quit",                 GTK_STOCK_QUIT,        N_( "_Quit" ),
    147       NULL,            NULL,                   G_CALLBACK( action_cb ) },
    148     { "select-all",           GTK_STOCK_SELECT_ALL,
    149       N_( "Select _All" ), "<control>A", NULL, G_CALLBACK( action_cb ) },
    150     { "deselect-all",         NULL,
    151       N_( "Dese_lect All" ), "<shift><control>A", NULL, G_CALLBACK(
    152           action_cb ) },
    153     { "edit-preferences",     GTK_STOCK_PREFERENCES, NULL,
    154       NULL,            NULL,                   G_CALLBACK( action_cb ) },
    155     { "show-torrent-details", GTK_STOCK_INFO,
    156       N_( "_Details" ), "<alt>Return", N_( "Torrent details" ), G_CALLBACK(
    157           action_cb ) },
    158     { "open-torrent-folder",  GTK_STOCK_OPEN,
    159       N_( "_Open Folder" ), NULL, NULL, G_CALLBACK( action_cb ) },
    160     { "show-about-dialog",    GTK_STOCK_ABOUT,       NULL,
    161       NULL,            NULL,                   G_CALLBACK( action_cb ) },
    162     { "help",                 GTK_STOCK_HELP,        N_( "_Contents" ),
    163       "F1",            NULL,                   G_CALLBACK( action_cb ) },
    164     { "update-tracker",       GTK_STOCK_NETWORK,
    165       N_( "Ask Tracker for _More Peers" ), NULL, NULL, G_CALLBACK(
    166           action_cb ) },
    167     { "present-main-window",  NULL,                  NULL,
    168       NULL,            NULL,                   G_CALLBACK( action_cb ) },
     111    { "torrent-menu", NULL, N_( "_Torrent" ), NULL, NULL, NULL  },
     112    { "view-menu", NULL, N_( "_View" ), NULL, NULL, NULL  },
     113    { "sort-menu", NULL, N_( "_Sort Torrents By" ), NULL, NULL, NULL },
     114    { "edit-menu", NULL, N_( "_Edit" ), NULL, NULL, NULL },
     115    { "help-menu", NULL, N_( "_Help" ), NULL, NULL, NULL },
     116    { "add-torrent-toolbar",  GTK_STOCK_ADD, NULL, NULL, N_( "Add a torrent" ),  G_CALLBACK( action_cb ) },
     117    { "add-torrent-menu", GTK_STOCK_ADD, N_( "_Add..." ), "<control>D", N_( "Add a torrent" ), G_CALLBACK( action_cb ) },
     118    { "start-torrent", GTK_STOCK_MEDIA_PLAY, N_( "_Start" ), "<control>S", N_( "Start torrent" ), G_CALLBACK( action_cb ) },
     119    { "show-stats", NULL, N_( "_Statistics" ), NULL, NULL, G_CALLBACK( action_cb ) },
     120    { "verify-torrent", NULL, N_( "_Verify Local Data" ), NULL, NULL, G_CALLBACK( action_cb ) },
     121    { "pause-torrent", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause" ), "<control>P", N_( "Pause torrent" ), G_CALLBACK( action_cb ) },
     122    { "pause-all-torrents", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause All" ), NULL, N_( "Pause all torrents" ), G_CALLBACK( action_cb ) },
     123    { "remove-torrent", GTK_STOCK_REMOVE, NULL, "Delete", N_( "Remove torrent" ), G_CALLBACK( action_cb ) },
     124    { "delete-torrent", GTK_STOCK_DELETE, N_( "_Delete Files and Remove" ), "<shift>Delete", NULL, G_CALLBACK( action_cb ) },
     125    { "new-torrent", GTK_STOCK_NEW, N_( "_New..." ), NULL, N_( "Create a torrent" ), G_CALLBACK( action_cb ) },
     126    { "quit", GTK_STOCK_QUIT, N_( "_Quit" ), NULL, NULL, G_CALLBACK( action_cb ) },
     127    { "select-all", GTK_STOCK_SELECT_ALL, N_( "Select _All" ), "<control>A", NULL, G_CALLBACK( action_cb ) },
     128    { "deselect-all", NULL, N_( "Dese_lect All" ), "<shift><control>A", NULL, G_CALLBACK( action_cb ) },
     129    { "edit-preferences", GTK_STOCK_PREFERENCES, NULL, NULL, NULL, G_CALLBACK( action_cb ) },
     130    { "show-torrent-properties", GTK_STOCK_PROPERTIES, NULL, "<alt>Return", N_( "Torrent properties" ), G_CALLBACK( action_cb ) },
     131    { "open-torrent-folder",  GTK_STOCK_OPEN, N_( "_Open Folder" ), NULL, NULL, G_CALLBACK( action_cb ) },
     132    { "show-about-dialog", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK( action_cb ) },
     133    { "help", GTK_STOCK_HELP, N_( "_Contents" ), "F1", NULL, G_CALLBACK( action_cb ) },
     134    { "update-tracker", GTK_STOCK_NETWORK, N_( "Ask Tracker for _More Peers" ), NULL, NULL, G_CALLBACK( action_cb ) },
     135    { "present-main-window", NULL, NULL, NULL, NULL, G_CALLBACK( action_cb ) },
    169136};
    170137
  • branches/1.5x/gtk/actions.h

    r6795 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/add-dialog.c

    r6998 r7664  
    11/*
    2  * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    4343
    4444static void
    45 save_recent_destination( const char * dir  )
     45save_recent_destination( TrCore * core, const char * dir  )
    4646{
    4747    int      i;
     
    7171        pref_string_set( key, l->data );
    7272    }
    73     pref_save( );
     73    pref_save( tr_core_session( core ) );
    7474
    7575    /* cleanup */
     
    117117    {
    118118        if( response != GTK_RESPONSE_ACCEPT )
     119        {
    119120            removeOldTorrent( data );
     121        }
    120122        else
    121123        {
    122             if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->
    123                                                                  run_check ) ) )
     124            if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->run_check ) ) )
    124125                tr_torrentStart( tr_torrent_handle( data->gtor ) );
     126
    125127            tr_core_add_torrent( data->core, data->gtor );
    126             if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->
    127                                                                  trash_check ) ) )
     128
     129            if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->trash_check ) ) )
     130
    128131                tr_file_trash_or_unlink( data->filename );
    129             save_recent_destination( data->downloadDir );
     132            save_recent_destination( data->core, data->downloadDir );
    130133        }
    131134    }
  • branches/1.5x/gtk/add-dialog.h

    r6998 r7664  
    11/*
    2  * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/conf.c

    r6862 r7664  
    4242#include "util.h"
    4343
     44#define MY_NAME "transmission"
     45
    4446static char * gl_confdir = NULL;
    4547static char * gl_lockpath = NULL;
     
    4749/* errstr may be NULL, this might be called before GTK is initialized */
    4850gboolean
    49 cf_init( const char *dir,
    50          char **    errstr )
     51cf_init( const char   * configDir,
     52         char        ** errstr )
    5153{
    5254    if( errstr != NULL )
    5355        *errstr = NULL;
    5456
    55     gl_confdir = g_strdup( dir );
     57    gl_confdir = g_strdup( configDir );
    5658
    5759    if( mkdir_p( gl_confdir, 0755 ) )
     
    152154getPrefs( void )
    153155{
    154     static tr_benc  dict;
     156    static tr_benc settings;
    155157    static gboolean loaded = FALSE;
    156158
    157159    if( !loaded )
    158160    {
    159         char * filename = getPrefsFilename( );
    160         if( tr_bencLoadJSONFile( filename, &dict ) )
    161             tr_bencInitDict( &dict, 100 );
    162         g_free( filename );
     161        tr_bencInitDict( &settings, 0 );
     162        tr_sessionLoadSettings( &settings, gl_confdir, MY_NAME );
    163163        loaded = TRUE;
    164164    }
    165165
    166     return &dict;
    167 }
    168 
    169 /***
    170 ****
    171 ***/
     166    return &settings;
     167}
     168
     169/***
     170****
     171***/
     172
     173tr_benc*
     174pref_get_all( void )
     175{
     176    return getPrefs( );
     177}
    172178
    173179int64_t
     
    184190              int64_t      value )
    185191{
    186     tr_benc * d = getPrefs( );
    187 
    188     tr_bencDictRemove( d, key );
    189     tr_bencDictAddInt( d, key, value );
     192    tr_bencDictAddInt( getPrefs( ), key, value );
    190193}
    191194
     
    259262                 const char * value )
    260263{
    261     tr_benc * d = getPrefs( );
    262 
    263     tr_bencDictRemove( d, key );
    264     tr_bencDictAddStr( d, key, value );
     264    tr_bencDictAddStr( getPrefs( ), key, value );
    265265}
    266266
     
    278278
    279279void
    280 pref_save( void )
    281 {
    282     char * filename = getPrefsFilename( );
    283     char * path = g_path_get_dirname( filename );
    284 
    285     mkdir_p( path, 0755 );
    286     tr_bencSaveJSONFile( filename, getPrefs( ) );
    287 
    288     g_free( path );
    289     g_free( filename );
     280pref_save( tr_session * session )
     281{
     282    tr_sessionSaveSettings( session, gl_confdir, getPrefs( ) );
    290283}
    291284
     
    317310{
    318311    assert( gl_confdir != NULL );
    319     return g_build_filename(
    320               g_get_home_dir( ), ".transmission", "gtk", "prefs", NULL );
     312
     313    return g_build_filename( g_get_home_dir( ), ".transmission", "gtk", "prefs", NULL );
    321314}
    322315
     
    325318{
    326319    assert( gl_confdir != NULL );
    327     return g_build_filename(
    328               g_get_home_dir( ), ".transmission", "gtk", "prefs.ini", NULL );
     320
     321    return g_build_filename( g_get_home_dir( ), ".transmission", "gtk", "prefs.ini", NULL );
    329322}
    330323
     
    332325getCompat121PrefsFilename( void )
    333326{
    334     return g_build_filename(
    335                g_get_user_config_dir( ), "transmission", "gtk", "prefs.ini",
    336                NULL );
     327    return g_build_filename( g_get_user_config_dir( ), "transmission", "gtk", "prefs.ini", NULL );
    337328}
    338329
     
    341332                    const char* newfile )
    342333{
    343     static struct pref_entry
    344     {
     334    static struct pref_entry {
    345335        const char*   oldkey;
    346336        const char*   newkey;
  • branches/1.5x/gtk/conf.h

    r6795 r7664  
    2323 *****************************************************************************/
    2424
     25struct tr_benc;
     26
    2527/**
    2628***
     
    3032#define TG_CONF_H
    3133
    32 int64_t     pref_int_get( const char * key );
     34int64_t          pref_int_get           ( const char * key );
     35void             pref_int_set           ( const char * key, int64_t value );
     36void             pref_int_set_default   ( const char * key, int64_t value );
    3337
    34 void        pref_int_set( const char * key,
    35                           int64_t      value );
     38gboolean         pref_flag_get          ( const char * key );
     39void             pref_flag_set          ( const char * key, gboolean value );
     40void             pref_flag_set_default  ( const char * key, gboolean value );
    3641
    37 void        pref_int_set_default( const char * key,
    38                                   int64_t      value );
     42const char*      pref_string_get        ( const char * key );
     43void             pref_string_set        ( const char * key, const char * value );
     44void             pref_string_set_default( const char * key, const char * value );
    3945
    40 gboolean    pref_flag_get( const char * key );
    41 
    42 void        pref_flag_set( const char * key,
    43                            gboolean     value );
    44 
    45 void        pref_flag_set_default( const char * key,
    46                                    gboolean     value );
    47 
    48 const char* pref_string_get( const char * key );
    49 
    50 void        pref_string_set( const char * key,
    51                              const char * value );
    52 
    53 void        pref_string_set_default( const char * key,
    54                                      const char * value );
    55 
    56 void        pref_save( void );
     46void             pref_save              ( tr_session * );
     47struct tr_benc*  pref_get_all           ( void );
    5748
    5849/**
  • branches/1.5x/gtk/details.c

    r7463 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    14791479    GtkWidget *     d, *n, *w;
    14801480    tr_torrent *    tor = tr_torrent_handle ( gtor );
    1481     char            sizeStr[64];
    14821481    char            title[512];
    14831482    const tr_info * info = tr_torrent_info ( gtor );
    14841483
    14851484    /* create the dialog */
    1486     tr_strlsize( sizeStr, info->totalSize, sizeof( sizeStr ) );
    1487     /* %1$s is torrent name
    1488        %2$s its file size */
    1489     g_snprintf( title, sizeof( title ), _(
    1490                     "Details for %1$s (%2$s)" ), info->name, sizeStr );
     1485    g_snprintf( title, sizeof( title ), _( "%s Properties" ), info->name );
    14911486    d = gtk_dialog_new_with_buttons ( title, parent, 0,
    14921487                                      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
  • branches/1.5x/gtk/details.h

    r6998 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/dialogs.c

    r6935 r7664  
    183183}
    184184
     185struct count_data
     186{
     187    int incomplete;
     188    int connected;
     189};
     190
    185191static void
    186 countBusyTorrents( gpointer gtor,
    187                    gpointer busyCount )
     192countBusyTorrents( gpointer gtor, gpointer gdata )
    188193{
    189194    const tr_stat * stat = tr_torrent_stat( gtor );
    190 
    191     if( stat->leftUntilDone || stat->peersConnected )
    192         ++( *(int*)busyCount );
     195    struct count_data * data = gdata;
     196
     197    if( stat->leftUntilDone ) ++data->incomplete;
     198    if( stat->peersConnected ) ++data->connected;
    193199}
    194200
     
    200206{
    201207    GtkWidget *         d;
     208    const int           count = g_slist_length( torrents );
     209    struct count_data   counts;
     210    const char        * primary_text;
     211    GString           * secondary_text;
    202212    struct DeleteData * dd;
    203     int                 busyCount;
    204     const int           count = g_slist_length( torrents );
    205     const char *        primary_text;
    206     const char *        secondary_text;
    207213
    208214    if( !count )
     
    214220    dd->delete_files = delete_files;
    215221
    216     busyCount = 0;
    217     g_slist_foreach( torrents, countBusyTorrents, &busyCount );
    218 
    219     if( !busyCount && !delete_files ) /* don't prompt boring torrents */
     222    counts.incomplete = 0;
     223    counts.connected = 0;
     224    g_slist_foreach( torrents, countBusyTorrents, &counts );
     225
     226    if( !counts.incomplete && !counts.connected && !delete_files ) /* don't prompt boring torrents */
    220227    {
    221228        removeTorrents( dd );
     
    225232
    226233    if( !delete_files )
    227         primary_text = ngettext( "Remove torrent?", "Remove torrents?",
     234    {
     235        primary_text = ngettext( "Remove torrent?",
     236                                 "Remove torrents?",
    228237                                 count );
     238    }
    229239    else
     240    {
    230241        primary_text = ngettext( "Delete this torrent's downloaded files?",
    231242                                 "Delete these torrents' downloaded files?",
    232243                                 count );
    233 
    234     if( busyCount > 1 )
    235         secondary_text = _(
    236             "Some of these torrents are incomplete or connected to peers." );
    237     else if( busyCount == 0 )
    238         secondary_text = NULL;
     244    }
     245
     246    secondary_text = g_string_new( NULL );
     247
     248    if( !counts.incomplete && !counts.connected )
     249    {
     250        /* boring -- no secondary text needed */
     251    }
     252    else if( count == counts.incomplete )
     253    {
     254        g_string_assign( secondary_text, ngettext( "This torrent has not finished downloading.",
     255                                                   "These torrents have not finished downloading.",
     256                                                   count ) );
     257    }
     258    else if( count == counts.connected )
     259    {
     260        g_string_assign( secondary_text, ngettext( "This torrent is connected to peers.",
     261                                                   "These torrents are connected to peers.",
     262                                                   count ) );
     263    }
    239264    else
    240         secondary_text = ngettext(
    241             "This torrent is incomplete or connected to peers.",
    242             "One of these torrents is incomplete or connected to peers.",
    243             count );
     265    {
     266        if( counts.connected )
     267            g_string_append( secondary_text, ngettext( "One of these torrents is connected to peers.",
     268                                                       "Some of these torrents are connected to peers.",
     269                                                       counts.connected ) );
     270        if( counts.connected && counts.incomplete )
     271            g_string_append( secondary_text, "\n" );
     272 
     273        if( counts.incomplete )
     274            g_string_assign( secondary_text, ngettext( "One of these torrents has not finished downloading.",
     275                                                       "Some of these torrents have not finished downloading.",
     276                                                       counts.incomplete ) );
     277    }
    244278
    245279    d = gtk_message_dialog_new_with_markup( parent,
     
    249283                                            "<big><b>%s</b></big>",
    250284                                            primary_text );
    251     if( secondary_text )
     285    if( secondary_text->len )
    252286        gtk_message_dialog_format_secondary_markup( GTK_MESSAGE_DIALOG( d ),
    253                                                     "%s", secondary_text );
     287                                                    "%s", secondary_text->str );
    254288    gtk_dialog_add_buttons( GTK_DIALOG( d ),
    255289                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
     
    265299    g_signal_connect( d, "response", G_CALLBACK( removeResponse ), dd );
    266300    gtk_widget_show_all( d );
    267 }
    268 
     301
     302    g_string_free( secondary_text, TRUE );
     303}
  • branches/1.5x/gtk/file-list.c

    r7463 r7664  
    661661                                           &path, &column, &cell_x, &cell_y ) )
    662662        {
    663             const char *   column_title = gtk_tree_view_column_get_title(
    664                 column );
    665             const gboolean downloadColumn =
    666                 !strcmp( column_title, Q_( "filedetails|Download" ) );
    667             const gboolean priorityColumn =
    668                 !strcmp( column_title, _( "Priority" ) );
     663            const char * column_title = gtk_tree_view_column_get_title( column );
     664            const gboolean downloadColumn = !strcmp( column_title, _( "Download" ) );
     665            const gboolean priorityColumn = !strcmp( column_title, _( "Priority" ) );
    669666            if( downloadColumn || priorityColumn )
    670667            {
     
    794791    col = GTK_TREE_VIEW_COLUMN ( g_object_new ( GTK_TYPE_TREE_VIEW_COLUMN,
    795792                                                "expand", TRUE,
    796                                                 /* Translators: this is a column
    797                                                    header in Files tab, Details
    798                                                    dialog;
    799                                                    Don't include the prefix
    800                                                    "filedetails|" in the
    801                                                    translation. */
    802                                                 "title", Q_( "filedetails|File" ),
     793                                                "title", _( "File" ),
    803794                                                NULL ) );
    804795    rend = gtk_cell_renderer_pixbuf_new( );
     
    809800    g_object_set( rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
    810801    gtk_tree_view_column_pack_start( col, rend, TRUE );
    811     gtk_tree_view_column_set_cell_data_func( col, rend, renderFilename,
    812                                              NULL,
    813                                              NULL );
     802    gtk_tree_view_column_set_cell_data_func( col, rend, renderFilename, NULL, NULL );
    814803    gtk_tree_view_column_set_resizable( col, TRUE );
    815804    gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
    816805
    817 
    818806    rend = gtk_cell_renderer_progress_new( );
    819     /* Translators: this is a column header in Files tab, Details dialog;
    820        Don't include the prefix "filedetails|" in the translation. */
    821     col = gtk_tree_view_column_new_with_attributes( Q_( "filedetails|Progress" ), rend, NULL );
     807    col = gtk_tree_view_column_new_with_attributes( _( "Progress" ), rend, NULL );
    822808    gtk_tree_view_column_set_cell_data_func( col, rend, renderProgress, NULL, NULL );
    823809    gtk_tree_view_column_set_resizable( col, FALSE );
     
    826812    /* add "enabled" column */
    827813    rend = gtk_cell_renderer_toggle_new( );
    828     /* Translators: this is a column header in Files tab, Details dialog;
    829        Don't include the prefix "filedetails|" in the translation.
    830        The items for this column are checkboxes (yes/no) */
    831     col = gtk_tree_view_column_new_with_attributes( Q_( "filedetails|Download" ), rend, NULL );
     814    col = gtk_tree_view_column_new_with_attributes( _( "Download" ), rend, NULL );
    832815    gtk_tree_view_column_set_cell_data_func( col, rend, renderDownload, NULL, NULL );
    833816    gtk_tree_view_column_set_resizable( col, FALSE );
  • branches/1.5x/gtk/hig.c

    r6795 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/hig.h

    r6998 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/main.c

    r7463 r7664  
    4343
    4444#include <libtransmission/transmission.h>
     45#include <libtransmission/rpcimpl.h>
    4546#include <libtransmission/utils.h>
    4647#include <libtransmission/version.h>
     
    6768#include <libtransmission/transmission.h>
    6869#include <libtransmission/version.h>
     70
     71#define MY_NAME "transmission"
    6972
    7073/* interval in milliseconds to update the torrent list display */
     
    109112struct cbdata
    110113{
    111     gboolean      minimized;
    112     gboolean      closing;
     114    unsigned int  isIconified : 1;
     115    unsigned int  isClosing   : 1;
    113116    guint         timer;
    114     guint         idle_hide_mainwindow_tag;
    115117    gpointer      icon;
    116118    GtkWindow *   wind;
     
    122124    GHashTable *  tor2details;
    123125    GHashTable *  details2tor;
     126    GtkTreeSelection * sel;
    124127};
    125128
     
    199202{
    200203    tr_torrent * tor;
    201 
    202204    gtk_tree_model_get( model, iter, MC_TORRENT_RAW, &tor, -1 );
    203205    *(int*)accumulated_status |= tr_torrentCanManualUpdate( tor );
     
    205207
    206208static void
    207 refreshTorrentActions( GtkTreeSelection * s )
     209refreshTorrentActions( struct cbdata * data )
    208210{
    209211    int                canUpdate;
    210212    struct counts_data counts;
     213    GtkTreeSelection * s = data->sel;
    211214
    212215    counts.activeCount = 0;
    213216    counts.inactiveCount = 0;
    214217    counts.totalCount = 0;
    215     gtk_tree_selection_selected_foreach( s, accumulateStatusForeach,
    216                                          &counts );
     218    gtk_tree_selection_selected_foreach( s, accumulateStatusForeach, &counts );
    217219    action_sensitize( "pause-torrent", counts.activeCount != 0 );
    218220    action_sensitize( "start-torrent", counts.inactiveCount != 0 );
     
    221223    action_sensitize( "verify-torrent", counts.totalCount != 0 );
    222224    action_sensitize( "open-torrent-folder", counts.totalCount == 1 );
    223     action_sensitize( "show-torrent-details", counts.totalCount == 1 );
     225    action_sensitize( "show-torrent-properties", counts.totalCount == 1 );
    224226
    225227    canUpdate = 0;
    226     gtk_tree_selection_selected_foreach( s, accumulateCanUpdateForeach,
    227                                          &canUpdate );
     228    gtk_tree_selection_selected_foreach( s, accumulateCanUpdateForeach, &canUpdate );
    228229    action_sensitize( "update-tracker", canUpdate != 0 );
    229230
     
    231232        GtkTreeView *  view = gtk_tree_selection_get_tree_view( s );
    232233        GtkTreeModel * model = gtk_tree_view_get_model( view );
    233         const int      torrentCount = gtk_tree_model_iter_n_children( model,
    234                                                                       NULL )
    235                                       != 0;
     234        const int  torrentCount = gtk_tree_model_iter_n_children( model, NULL ) != 0;
    236235        action_sensitize( "select-all", torrentCount != 0 );
    237236        action_sensitize( "deselect-all", torrentCount != 0 );
    238237    }
    239 }
    240 
    241 static void
    242 selectionChangedCB( GtkTreeSelection * s,
    243                     gpointer unused    UNUSED )
    244 {
    245     refreshTorrentActions( s );
     238
     239    {
     240        tr_torrent * tor = NULL;
     241        tr_session * session = tr_core_session( data->core );
     242        int activeCount = 0;
     243        while(( tor = tr_torrentNext( session, tor )))
     244            if( TR_STATUS_IS_ACTIVE( tr_torrentGetActivity( tor )))
     245                ++activeCount;
     246        action_sensitize( "pause-all-torrents", activeCount != 0 );
     247    }
     248}
     249
     250static void
     251selectionChangedCB( GtkTreeSelection * s UNUSED, gpointer data )
     252{
     253    refreshTorrentActions( data );
    246254}
    247255
     
    264272        pref_int_set( PREF_KEY_MAIN_WINDOW_WIDTH, w );
    265273        pref_int_set( PREF_KEY_MAIN_WINDOW_HEIGHT, h );
    266     }
    267 }
    268 
    269 static void
    270 windowStateChanged( GtkWidget * widget    UNUSED,
    271                     GdkEventWindowState * event,
    272                     gpointer              gdata )
    273 {
    274     if( event->changed_mask & GDK_WINDOW_STATE_ICONIFIED )
    275     {
    276         struct cbdata * cbdata = gdata;
    277         cbdata->minimized =
    278             ( event->new_window_state &
    279               GDK_WINDOW_STATE_ICONIFIED ) ? 1 : 0;
    280274    }
    281275}
     
    361355    gboolean            startpaused = FALSE;
    362356    gboolean            startminimized = FALSE;
    363     char *              domain = "transmission";
     357    char *              domain = MY_NAME;
    364358    char *              configDir = NULL;
    365359    tr_lockfile_state_t tr_state;
     
    411405
    412406    if( configDir == NULL )
    413         configDir = (char*) tr_getDefaultConfigDir( );
     407        configDir = (char*) tr_getDefaultConfigDir( MY_NAME );
    414408
    415409    tr_notify_init( );
    416 
    417410    didinit = cf_init( configDir, NULL ); /* must come before actions_init */
    418411    tr_prefs_init_global( );
     412
    419413    myUIManager = gtk_ui_manager_new ( );
    420414    actions_init ( myUIManager, cbdata );
    421     gtk_ui_manager_add_ui_from_string ( myUIManager, fallback_ui_file, -1,
    422                                         NULL );
     415    gtk_ui_manager_add_ui_from_string ( myUIManager, fallback_ui_file, -1, NULL );
    423416    gtk_ui_manager_ensure_update ( myUIManager );
    424     gtk_window_set_default_icon_name ( "transmission" );
     417    gtk_window_set_default_icon_name ( MY_NAME );
    425418
    426419    setupsighandlers( ); /* set up handlers for fatal signals */
     
    449442    {
    450443        GtkWindow * win;
    451 
    452         tr_session * h = tr_sessionInitFull(
    453             configDir,
    454             "gtk",
    455             pref_string_get( PREF_KEY_DOWNLOAD_DIR ),
    456             pref_flag_get( PREF_KEY_PEX ),
    457             pref_flag_get( PREF_KEY_PORT_FORWARDING ),
    458             pref_int_get( PREF_KEY_PORT ),
    459             pref_int_get( PREF_KEY_ENCRYPTION ),
    460             pref_flag_get( PREF_KEY_LAZY_BITFIELD ),
    461             pref_flag_get( PREF_KEY_UL_LIMIT_ENABLED ),
    462             pref_int_get( PREF_KEY_UL_LIMIT ),
    463             pref_flag_get( PREF_KEY_DL_LIMIT_ENABLED ),
    464             pref_int_get( PREF_KEY_DL_LIMIT ),
    465             pref_int_get( PREF_KEY_MAX_PEERS_GLOBAL ),
    466             pref_int_get( PREF_KEY_MSGLEVEL ),
    467             TRUE,                 /* message queueing */
    468             pref_flag_get( PREF_KEY_BLOCKLIST_ENABLED ),
    469             pref_int_get( PREF_KEY_PEER_SOCKET_TOS ),
    470             pref_flag_get( PREF_KEY_RPC_ENABLED ),
    471             pref_int_get( PREF_KEY_RPC_PORT ),
    472             pref_flag_get( PREF_KEY_RPC_WHITELIST_ENABLED ),
    473             pref_string_get( PREF_KEY_RPC_WHITELIST ),
    474             pref_flag_get( PREF_KEY_RPC_AUTH_ENABLED ),
    475             pref_string_get( PREF_KEY_RPC_USERNAME ),
    476             pref_string_get( PREF_KEY_RPC_PASSWORD ),
    477             pref_flag_get( PREF_KEY_PROXY_SERVER_ENABLED ),
    478             pref_string_get( PREF_KEY_PROXY_SERVER ),
    479             pref_int_get( PREF_KEY_PROXY_PORT ),
    480             pref_int_get( PREF_KEY_PROXY_TYPE ),
    481             pref_flag_get( PREF_KEY_PROXY_AUTH_ENABLED ),
    482             pref_string_get( PREF_KEY_PROXY_USERNAME ),
    483             pref_string_get( PREF_KEY_PROXY_PASSWORD ) );
    484 
    485         cbdata->core = tr_core_new( h );
     444        tr_session * session;
     445
     446        /* initialize the libtransmission session */
     447        session = tr_sessionInit( "gtk", configDir, TRUE, pref_get_all( ) );
     448        cbdata->core = tr_core_new( session );
    486449
    487450        /* create main window now to be a parent to any error dialogs */
    488451        win = GTK_WINDOW( tr_window_new( myUIManager, cbdata->core ) );
    489         g_signal_connect( win, "window-state-event",
    490                           G_CALLBACK( windowStateChanged ), cbdata );
    491         g_signal_connect( win, "size-allocate",
    492                           G_CALLBACK( onMainWindowSizeAllocated ), cbdata );
     452        g_signal_connect( win, "size-allocate", G_CALLBACK( onMainWindowSizeAllocated ), cbdata );
    493453
    494454        appsetup( win, argfiles, cbdata, startpaused, startminimized );
    495         tr_sessionSetRPCCallback( h, onRPCChanged, cbdata );
     455        tr_sessionSetRPCCallback( session, onRPCChanged, cbdata );
    496456        gtr_blocklist_maybe_autoupdate( cbdata->core );
    497457
     
    566526            tr_inf ( _( "Ending use of scheduled bandwidth limits" ) );
    567527
    568             b = pref_flag_get( PREF_KEY_DL_LIMIT_ENABLED );
     528            b = pref_flag_get( TR_PREFS_KEY_DSPEED_ENABLED );
    569529            tr_sessionSetSpeedLimitEnabled( tr, TR_DOWN, b );
    570             limit = pref_int_get( PREF_KEY_DL_LIMIT );
     530            limit = pref_int_get( TR_PREFS_KEY_DSPEED );
    571531            tr_sessionSetSpeedLimit( tr, TR_DOWN, limit );
    572             b = pref_flag_get( PREF_KEY_UL_LIMIT_ENABLED );
     532            b = pref_flag_get( TR_PREFS_KEY_USPEED_ENABLED );
    573533            tr_sessionSetSpeedLimitEnabled( tr, TR_UP, b );
    574             limit = pref_int_get( PREF_KEY_UL_LIMIT );
     534            limit = pref_int_get( TR_PREFS_KEY_USPEED );
    575535            tr_sessionSetSpeedLimit( tr, TR_UP, limit );
    576536        }
     
    604564          struct cbdata * cbdata,
    605565          gboolean        forcepause,
    606           gboolean        minimized )
     566          gboolean        isIconified )
    607567{
    608568    const pref_flag_t start =
     
    611571
    612572    /* fill out cbdata */
    613     cbdata->wind       = NULL;
    614     cbdata->icon       = NULL;
    615     cbdata->msgwin     = NULL;
    616     cbdata->prefs      = NULL;
    617     cbdata->timer      = 0;
    618     cbdata->closing    = FALSE;
    619     cbdata->errqueue   = NULL;
    620     cbdata->dupqueue   = NULL;
    621     cbdata->minimized  = minimized;
    622 
    623     if( minimized )
     573    cbdata->wind         = NULL;
     574    cbdata->icon         = NULL;
     575    cbdata->msgwin       = NULL;
     576    cbdata->prefs        = NULL;
     577    cbdata->timer        = 0;
     578    cbdata->isClosing    = 0;
     579    cbdata->errqueue     = NULL;
     580    cbdata->dupqueue     = NULL;
     581    cbdata->isIconified  = isIconified;
     582
     583    if( isIconified )
    624584        pref_flag_set( PREF_KEY_SHOW_TRAY_ICON, TRUE );
    625585
     
    656616
    657617    /* either show the window or iconify it */
    658     if( !minimized )
     618    if( !isIconified )
    659619        gtk_widget_show( GTK_WIDGET( wind ) );
    660620    else
     
    666626}
    667627
    668 /**
    669  * hideMainWindow, and the timeout hack in toggleMainWindow,
    670  * are loosely cribbed from Colin Walters' rb-shell.c in Rhythmbox
    671  */
    672 static gboolean
    673 idle_hide_mainwindow( gpointer window )
    674 {
    675     gtk_widget_hide( window );
    676     return FALSE;
    677 }
    678 
    679 static void
    680 hideMainWindow( struct cbdata * cbdata )
    681 {
    682 #if defined( STATUS_ICON_SUPPORTED ) && defined( GDK_WINDOWING_X11 )
    683     GdkRectangle bounds;
    684     gulong       data[4];
    685     Display *    dpy;
    686     GdkWindow *  gdk_window;
    687 
    688     gtk_status_icon_get_geometry( GTK_STATUS_ICON(
    689                                       cbdata->icon ), NULL, &bounds, NULL );
    690     gdk_window = GTK_WIDGET ( cbdata->wind )->window;
    691     dpy = gdk_x11_drawable_get_xdisplay ( gdk_window );
    692 
    693     data[0] = bounds.x;
    694     data[1] = bounds.y;
    695     data[2] = bounds.width;
    696     data[3] = bounds.height;
    697 
    698     XChangeProperty ( dpy,
    699                       GDK_WINDOW_XID ( gdk_window ),
    700                       gdk_x11_get_xatom_by_name_for_display (
    701                           gdk_drawable_get_display ( gdk_window ),
    702                           "_NET_WM_ICON_GEOMETRY" ),
    703                       XA_CARDINAL, 32, PropModeReplace,
    704                       (guchar*)&data, 4 );
    705 
    706     gtk_window_set_skip_taskbar_hint( cbdata->wind, TRUE );
     628static void
     629tr_window_present( GtkWindow * window )
     630{
     631#if GTK_CHECK_VERSION( 2, 8, 0 )
     632    gtk_window_present_with_time( window, gtk_get_current_event_time( ) );
     633#else
     634    gtk_window_present( window );
    707635#endif
    708     gtk_window_iconify( cbdata->wind );
    709 }
    710 
    711 static void
    712 clearTag( guint * tag )
    713 {
    714     if( *tag )
    715         g_source_remove( *tag );
    716     *tag = 0;
    717636}
    718637
    719638static void
    720639toggleMainWindow( struct cbdata * cbdata,
    721                   gboolean        present )
     640                  gboolean        doPresent )
    722641{
    723642    GtkWindow * window = GTK_WINDOW( cbdata->wind );
    724     const int   hide = !cbdata->minimized;
    725     static int  x = 0, y = 0;
    726 
    727     if( ( !present ) && hide )
     643    const int   doShow = cbdata->isIconified;
     644    static int  x = 0;
     645    static int  y = 0;
     646
     647    if( doShow || doPresent )
     648    {
     649        cbdata->isIconified = 0;
     650        gtk_window_set_skip_taskbar_hint( window, FALSE );
     651        gtk_window_move( window, x, y );
     652        gtk_widget_show( GTK_WIDGET( window ) );
     653        tr_window_present( window );
     654    }
     655    else
    728656    {
    729657        gtk_window_get_position( window, &x, &y );
    730         clearTag( &cbdata->idle_hide_mainwindow_tag );
    731         hideMainWindow( cbdata );
    732         cbdata->idle_hide_mainwindow_tag = g_timeout_add(
    733             100, idle_hide_mainwindow, window );
    734     }
    735     else
    736     {
    737         gtk_window_set_skip_taskbar_hint( window, FALSE );
    738         if( x != 0 && y != 0 )
    739             gtk_window_move( window, x, y );
    740         gtk_widget_show( GTK_WIDGET( window ) );
    741         gtk_window_deiconify( window );
    742 #if GTK_CHECK_VERSION( 2, 8, 0 )
    743         gtk_window_present_with_time( window, gtk_get_current_event_time( ) );
    744 #else
    745         gtk_window_present( window );
    746 #endif
     658        gtk_window_set_skip_taskbar_hint( window, TRUE );
     659        gtk_widget_hide( GTK_WIDGET( window ) );
     660        cbdata->isIconified = 1;
    747661    }
    748662}
     
    765679static void
    766680rowChangedCB( GtkTreeModel  * model UNUSED,
    767               GtkTreePath *        path,
     681              GtkTreePath   * path,
    768682              GtkTreeIter   * iter  UNUSED,
    769               gpointer              sel )
    770 {
    771     if( gtk_tree_selection_path_is_selected ( sel, path ) )
    772         refreshTorrentActions( GTK_TREE_SELECTION( sel ) );
     683              gpointer        gdata )
     684{
     685    struct cbdata * data = gdata;
     686    if( gtk_tree_selection_path_is_selected ( data->sel, path ) )
     687        refreshTorrentActions( gdata );
    773688}
    774689
     
    782697    g_assert( NULL == cbdata->wind );
    783698    cbdata->wind = GTK_WINDOW( wind );
    784 
    785     sel = tr_window_get_selection( cbdata->wind );
    786     g_signal_connect( sel, "changed", G_CALLBACK(
    787                           selectionChangedCB ), NULL );
    788     selectionChangedCB( sel, NULL );
     699    cbdata->sel = sel = GTK_TREE_SELECTION( tr_window_get_selection( cbdata->wind ) );
     700
     701    g_signal_connect( sel, "changed", G_CALLBACK( selectionChangedCB ), cbdata );
     702    selectionChangedCB( sel, cbdata );
    789703    model = tr_core_model( cbdata->core );
    790     g_signal_connect( model, "row-changed", G_CALLBACK( rowChangedCB ), sel );
     704    g_signal_connect( model, "row-changed", G_CALLBACK( rowChangedCB ), cbdata );
    791705    g_signal_connect( wind, "delete-event", G_CALLBACK( winclose ), cbdata );
    792     refreshTorrentActions( sel );
     706    refreshTorrentActions( cbdata );
    793707
    794708    setupdrag( GTK_WIDGET( wind ), cbdata );
     
    1003917    GtkWidget * w;
    1004918
    1005     for( l = *files; l; l = l->next )
    1006         g_string_append_printf( s, "%s\n", (const char*)l->data );
     919    if( g_slist_length( *files ) > 1 ) {
     920        for( l=*files; l!=NULL; l=l->next )
     921            g_string_append_printf( s, "\xE2\x88\x99 %s\n", (const char*)l->data );
     922    } else {
     923        for( l=*files; l!=NULL; l=l->next )
     924            g_string_append_printf( s, "%s\n", (const char*)l->data );
     925    }
    1007926    w = gtk_message_dialog_new( window,
    1008927                                GTK_DIALOG_DESTROY_WITH_PARENT,
     
    1028947        flushAddTorrentErrors( GTK_WINDOW( cbdata->wind ),
    1029948                               ngettext( "Couldn't add corrupt torrent",
    1030                                         "Couldn't add corrupt torrents",
    1031                                         g_slist_length( cbdata->errqueue ) ),
     949                                         "Couldn't add corrupt torrents",
     950                                         g_slist_length( cbdata->errqueue ) ),
    1032951                               &cbdata->errqueue );
    1033952
     
    1035954        flushAddTorrentErrors( GTK_WINDOW( cbdata->wind ),
    1036955                               ngettext( "Couldn't add duplicate torrent",
    1037                                         "Couldn't add duplicate torrents",
    1038                                         g_slist_length( cbdata->dupqueue ) ),
     956                                         "Couldn't add duplicate torrents",
     957                                         g_slist_length( cbdata->dupqueue ) ),
    1039958                               &cbdata->dupqueue );
    1040959}
     
    1056975
    1057976        case TR_EDUPLICATE:
    1058             c->dupqueue =
    1059                 g_slist_append( c->dupqueue, g_path_get_basename( msg ) );
     977            c->dupqueue = g_slist_append( c->dupqueue, g_strdup( msg ) );
    1060978            break;
    1061979
     
    11101028    tr_session     * tr     = tr_core_session( cbdata->core );
    11111029
    1112     if( !strcmp( key, PREF_KEY_ENCRYPTION ) )
     1030    if( !strcmp( key, TR_PREFS_KEY_ENCRYPTION ) )
    11131031    {
    11141032        const int encryption = pref_int_get( key );
     
    11161034        tr_sessionSetEncryption( tr, encryption );
    11171035    }
    1118     else if( !strcmp( key, PREF_KEY_BLOCKLIST_ENABLED ) )
    1119     {
    1120         tr_blocklistSetEnabled( tr, pref_flag_get( key ) );
    1121     }
    1122     else if( !strcmp( key, PREF_KEY_DOWNLOAD_DIR ) )
     1036    else if( !strcmp( key, TR_PREFS_KEY_DOWNLOAD_DIR ) )
    11231037    {
    11241038        tr_sessionSetDownloadDir( tr, pref_string_get( key ) );
    11251039    }
    1126     else if( !strcmp( key, PREF_KEY_PORT ) )
     1040    else if( !strcmp( key, TR_PREFS_KEY_MSGLEVEL ) )
     1041    {
     1042        tr_setMessageLevel( pref_int_get( key ) );
     1043    }
     1044    else if( !strcmp( key, TR_PREFS_KEY_PEER_PORT_RANDOM_ENABLED ) )
     1045    {
     1046        /* FIXME */
     1047    }
     1048    else if( !strcmp( key, TR_PREFS_KEY_PEER_PORT ) )
    11271049    {
    11281050        const int port = pref_int_get( key );
    11291051        tr_sessionSetPeerPort( tr, port );
     1052    }
     1053    else if( !strcmp( key, TR_PREFS_KEY_BLOCKLIST_ENABLED ) )
     1054    {
     1055        const gboolean flag = pref_flag_get( key );
     1056        tr_blocklistSetEnabled( tr, flag );
    11301057    }
    11311058    else if( !strcmp( key, PREF_KEY_SHOW_TRAY_ICON ) )
     
    11401067        }
    11411068    }
    1142     else if( !strcmp( key, PREF_KEY_DL_LIMIT_ENABLED ) )
     1069    else if( !strcmp( key, TR_PREFS_KEY_DSPEED_ENABLED ) )
    11431070    {
    11441071        const gboolean b = pref_flag_get( key );
    11451072        tr_sessionSetSpeedLimitEnabled( tr, TR_DOWN, b );
    11461073    }
    1147     else if( !strcmp( key, PREF_KEY_DL_LIMIT ) )
     1074    else if( !strcmp( key, TR_PREFS_KEY_DSPEED ) )
    11481075    {
    11491076        const int limit = pref_int_get( key );
    11501077        tr_sessionSetSpeedLimit( tr, TR_DOWN, limit );
    11511078    }
    1152     else if( !strcmp( key, PREF_KEY_UL_LIMIT_ENABLED ) )
     1079    else if( !strcmp( key, TR_PREFS_KEY_USPEED_ENABLED ) )
    11531080    {
    11541081        const gboolean b = pref_flag_get( key );
    11551082        tr_sessionSetSpeedLimitEnabled( tr, TR_UP, b );
    11561083    }
    1157     else if( !strcmp( key, PREF_KEY_UL_LIMIT ) )
     1084    else if( !strcmp( key, TR_PREFS_KEY_USPEED ) )
    11581085    {
    11591086        const int limit = pref_int_get( key );
     
    11641091        updateScheduledLimits( tr );
    11651092    }
    1166     else if( !strcmp( key, PREF_KEY_PORT_FORWARDING ) )
     1093    else if( !strcmp( key, TR_PREFS_KEY_PORT_FORWARDING ) )
    11671094    {
    11681095        tr_sessionSetPortForwardingEnabled( tr, pref_flag_get( key ) );
    11691096    }
    1170     else if( !strcmp( key, PREF_KEY_PEX ) )
     1097    else if( !strcmp( key, TR_PREFS_KEY_PEX_ENABLED ) )
    11711098    {
    11721099        tr_sessionSetPexEnabled( tr, pref_flag_get( key ) );
    11731100    }
    1174     else if( !strcmp( key, PREF_KEY_RPC_ENABLED ) )
     1101    else if( !strcmp( key, TR_PREFS_KEY_RPC_PORT ) )
     1102    {
     1103        tr_sessionSetRPCPort( tr, pref_int_get( key ) );
     1104    }
     1105    else if( !strcmp( key, TR_PREFS_KEY_RPC_ENABLED ) )
    11751106    {
    11761107        tr_sessionSetRPCEnabled( tr, pref_flag_get( key ) );
    11771108    }
    1178     else if( !strcmp( key, PREF_KEY_RPC_PORT ) )
    1179     {
    1180         tr_sessionSetRPCPort( tr, pref_int_get( key ) );
    1181     }
    1182     else if( !strcmp( key, PREF_KEY_RPC_ENABLED ) )
    1183     {
    1184         tr_sessionSetRPCEnabled( tr, pref_flag_get( key ) );
    1185     }
    1186     else if( !strcmp( key, PREF_KEY_RPC_WHITELIST ) )
     1109    else if( !strcmp( key, TR_PREFS_KEY_RPC_WHITELIST ) )
    11871110    {
    11881111        const char * s = pref_string_get( key );
    11891112        tr_sessionSetRPCWhitelist( tr, s );
    11901113    }
    1191     else if( !strcmp( key, PREF_KEY_RPC_WHITELIST_ENABLED ) )
     1114    else if( !strcmp( key, TR_PREFS_KEY_RPC_WHITELIST_ENABLED ) )
    11921115    {
    11931116        tr_sessionSetRPCWhitelistEnabled( tr, pref_flag_get( key ) );
    11941117    }
    1195     else if( !strcmp( key, PREF_KEY_RPC_USERNAME ) )
     1118    else if( !strcmp( key, TR_PREFS_KEY_RPC_USERNAME ) )
    11961119    {
    11971120        const char * s = pref_string_get( key );
    11981121        tr_sessionSetRPCUsername( tr, s );
    11991122    }
    1200     else if( !strcmp( key, PREF_KEY_RPC_PASSWORD ) )
     1123    else if( !strcmp( key, TR_PREFS_KEY_RPC_PASSWORD ) )
    12011124    {
    12021125        const char * s = pref_string_get( key );
    12031126        tr_sessionSetRPCPassword( tr, s );
    12041127    }
    1205     else if( !strcmp( key, PREF_KEY_RPC_AUTH_ENABLED ) )
     1128    else if( !strcmp( key, TR_PREFS_KEY_RPC_AUTH_REQUIRED ) )
    12061129    {
    12071130        const gboolean enabled = pref_flag_get( key );
    12081131        tr_sessionSetRPCPasswordEnabled( tr, enabled );
    12091132    }
    1210     else if( !strcmp( key, PREF_KEY_PROXY_SERVER ) )
     1133    else if( !strcmp( key, TR_PREFS_KEY_PROXY ) )
    12111134    {
    12121135        const char * s = pref_string_get( key );
    12131136        tr_sessionSetProxy( tr, s );
    12141137    }
    1215     else if( !strcmp( key, PREF_KEY_PROXY_TYPE ) )
     1138    else if( !strcmp( key, TR_PREFS_KEY_PROXY_TYPE ) )
    12161139    {
    12171140        const int i = pref_int_get( key );
    12181141        tr_sessionSetProxyType( tr, i );
    12191142    }
    1220     else if( !strcmp( key, PREF_KEY_PROXY_SERVER_ENABLED ) )
     1143    else if( !strcmp( key, TR_PREFS_KEY_PROXY_ENABLED ) )
    12211144    {
    12221145        const gboolean enabled = pref_flag_get( key );
    12231146        tr_sessionSetProxyEnabled( tr, enabled );
    12241147    }
    1225     else if( !strcmp( key, PREF_KEY_PROXY_AUTH_ENABLED ) )
     1148    else if( !strcmp( key, TR_PREFS_KEY_PROXY_AUTH_ENABLED ) )
    12261149    {
    12271150        const gboolean enabled = pref_flag_get( key );
    12281151        tr_sessionSetProxyAuthEnabled( tr, enabled );
    12291152    }
    1230     else if( !strcmp( key, PREF_KEY_PROXY_USERNAME ) )
     1153    else if( !strcmp( key, TR_PREFS_KEY_PROXY_USERNAME ) )
    12311154    {
    12321155        const char * s = pref_string_get( key );
    12331156        tr_sessionSetProxyUsername( tr, s );
    12341157    }
    1235     else if( !strcmp( key, PREF_KEY_PROXY_PASSWORD ) )
     1158    else if( !strcmp( key, TR_PREFS_KEY_PROXY_PASSWORD ) )
    12361159    {
    12371160        const char * s = pref_string_get( key );
    12381161        tr_sessionSetProxyPassword( tr, s );
    12391162    }
    1240     else if( !strcmp( key, PREF_KEY_PORT ) )
     1163    else if( !strcmp( key, TR_PREFS_KEY_PROXY_PORT ) )
    12411164    {
    12421165        tr_sessionSetProxyPort( tr, pref_int_get( key ) );
     1166    }
     1167    else if( !strcmp( key, TR_PREFS_KEY_RPC_PASSWORD ) )
     1168    {
     1169        const char * s = pref_string_get( key );
     1170        tr_sessionSetProxyPassword( tr, s );
    12431171    }
    12441172}
     
    12481176{
    12491177    struct cbdata *data = gdata;
    1250     const gboolean done = data->closing || global_sigcount;
     1178    const gboolean done = data->isClosing || global_sigcount;
    12511179
    12521180    if( !done )
     
    12601188
    12611189        /* update the actions */
    1262         refreshTorrentActions( tr_window_get_selection( data->wind ) );
     1190        refreshTorrentActions( data );
    12631191    }
    12641192
     
    12991227                           "website-label", website_url,
    13001228                           "copyright",
    1301                            _(
    1302                                "Copyright 2005-2008 The Transmission Project" ),
    1303                            "logo-icon-name", "transmission",
     1229                           _( "Copyright 2005-2009 The Transmission Project" ),
     1230                           "logo-icon-name", MY_NAME,
    13041231#ifdef SHOW_LICENSE
    13051232                           "license", LICENSE,
     
    14531380}
    14541381
     1382static void
     1383pauseAllTorrents( struct cbdata * data )
     1384{
     1385    tr_session * session = tr_core_session( data->core );
     1386    const char * cmd = "{ \"method\": \"torrent-stop\" }";
     1387    tr_rpc_request_exec_json( session, cmd, strlen( cmd ), NULL );
     1388}
     1389
    14551390void
    1456 doAction( const char * action_name,
    1457           gpointer     user_data )
     1391doAction( const char * action_name, gpointer user_data )
    14581392{
    14591393    struct cbdata * data = user_data;
    14601394    gboolean        changed = FALSE;
    14611395
    1462     if( !strcmp ( action_name, "add-torrent-menu" )
     1396    if(  !strcmp( action_name, "add-torrent-menu" )
    14631397      || !strcmp( action_name, "add-torrent-toolbar" ) )
    14641398    {
    14651399        addDialog( data->wind, data->core );
    14661400    }
    1467     else if( !strcmp ( action_name, "show-stats" ) )
    1468     {
    1469         GtkWidget * dialog = stats_dialog_create( data->wind,
    1470                                                   data->core );
     1401    else if( !strcmp( action_name, "show-stats" ) )
     1402    {
     1403        GtkWidget * dialog = stats_dialog_create( data->wind, data->core );
    14711404        gtk_widget_show( dialog );
    14721405    }
    1473     else if( !strcmp ( action_name, "start-torrent" ) )
     1406    else if( !strcmp( action_name, "start-torrent" ) )
    14741407    {
    14751408        GtkTreeSelection * s = tr_window_get_selection( data->wind );
     
    14771410        changed |= gtk_tree_selection_count_selected_rows( s ) != 0;
    14781411    }
    1479     else if( !strcmp ( action_name, "pause-torrent" ) )
     1412    else if( !strcmp( action_name, "pause-all-torrents" ) )
     1413    {
     1414        pauseAllTorrents( data );
     1415    }
     1416    else if( !strcmp( action_name, "pause-torrent" ) )
    14801417    {
    14811418        GtkTreeSelection * s = tr_window_get_selection( data->wind );
     
    14831420        changed |= gtk_tree_selection_count_selected_rows( s ) != 0;
    14841421    }
    1485     else if( !strcmp ( action_name, "verify-torrent" ) )
     1422    else if( !strcmp( action_name, "verify-torrent" ) )
    14861423    {
    14871424        GtkTreeSelection * s = tr_window_get_selection( data->wind );
     
    14891426        changed |= gtk_tree_selection_count_selected_rows( s ) != 0;
    14901427    }
    1491     else if( !strcmp ( action_name, "open-torrent-folder" ) )
     1428    else if( !strcmp( action_name, "open-torrent-folder" ) )
    14921429    {
    14931430        GtkTreeSelection * s = tr_window_get_selection( data->wind );
    14941431        gtk_tree_selection_selected_foreach( s, openFolderForeach, data );
    14951432    }
    1496     else if( !strcmp ( action_name, "show-torrent-details" ) )
     1433    else if( !strcmp( action_name, "show-torrent-properties" ) )
    14971434    {
    14981435        GtkTreeSelection * s = tr_window_get_selection( data->wind );
     
    15051442                                             data->wind );
    15061443    }
    1507     else if( !strcmp ( action_name, "new-torrent" ) )
     1444    else if( !strcmp( action_name, "new-torrent" ) )
    15081445    {
    15091446        GtkWidget * w = make_meta_ui( GTK_WINDOW( data->wind ),
     
    15191456        removeSelected( data, TRUE );
    15201457    }
    1521     else if( !strcmp ( action_name, "quit" ) )
     1458    else if( !strcmp( action_name, "quit" ) )
    15221459    {
    15231460        askquit( data->core, data->wind, wannaquit, data );
    15241461    }
    1525     else if( !strcmp ( action_name, "select-all" ) )
     1462    else if( !strcmp( action_name, "select-all" ) )
    15261463    {
    15271464        GtkTreeSelection * s = tr_window_get_selection( data->wind );
    15281465        gtk_tree_selection_select_all( s );
    15291466    }
    1530     else if( !strcmp ( action_name, "deselect-all" ) )
     1467    else if( !strcmp( action_name, "deselect-all" ) )
    15311468    {
    15321469        GtkTreeSelection * s = tr_window_get_selection( data->wind );
    15331470        gtk_tree_selection_unselect_all( s );
    15341471    }
    1535     else if( !strcmp ( action_name, "edit-preferences" ) )
     1472    else if( !strcmp( action_name, "edit-preferences" ) )
    15361473    {
    15371474        if( NULL == data->prefs )
     
    15441481        }
    15451482    }
    1546     else if( !strcmp ( action_name, "toggle-message-log" ) )
     1483    else if( !strcmp( action_name, "toggle-message-log" ) )
    15471484    {
    15481485        if( !data->msgwin )
     
    15601497        }
    15611498    }
    1562     else if( !strcmp ( action_name, "show-about-dialog" ) )
     1499    else if( !strcmp( action_name, "show-about-dialog" ) )
    15631500    {
    15641501        about( data->wind );
     
    15701507        g_free( url );
    15711508    }
    1572     else if( !strcmp ( action_name, "toggle-main-window" ) )
     1509    else if( !strcmp( action_name, "toggle-main-window" ) )
    15731510    {
    15741511        toggleMainWindow( data, FALSE );
    15751512    }
    1576     else if( !strcmp ( action_name, "present-main-window" ) )
     1513    else if( !strcmp( action_name, "present-main-window" ) )
    15771514    {
    15781515        toggleMainWindow( data, TRUE );
  • branches/1.5x/gtk/makemeta-ui.c

    r6998 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/makemeta-ui.h

    r6978 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/msgwin.c

    r7463 r7664  
    11/*
    2  * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    6969
    7070        tr_setMessageLevel( level );
    71         tr_core_set_pref_int( data->core, PREF_KEY_MSGLEVEL, level );
     71        tr_core_set_pref_int( data->core, TR_PREFS_KEY_MSGLEVEL, level );
    7272        data->maxLevel = level;
    7373        gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( data->filter ) );
     
    406406    store = gtk_list_store_new ( 2, G_TYPE_STRING, G_TYPE_INT );
    407407
    408     curlevel = pref_int_get( PREF_KEY_MSGLEVEL );
     408    curlevel = pref_int_get( TR_PREFS_KEY_MSGLEVEL );
    409409    for( i = ii = 0; i < G_N_ELEMENTS( trLevels ); ++i )
    410410    {
     
    520520                                          COL_SEQUENCE,
    521521                                          GTK_SORT_ASCENDING );
    522     data->maxLevel = pref_int_get( PREF_KEY_MSGLEVEL );
     522    data->maxLevel = pref_int_get( TR_PREFS_KEY_MSGLEVEL );
    523523    gtk_tree_model_filter_set_visible_func( GTK_TREE_MODEL_FILTER( data->
    524524                                                                   filter ),
  • branches/1.5x/gtk/msgwin.h

    r6795 r7664  
    11/*
    2  * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/notify.c

    r6795 r7664  
    11/*
    2  * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/notify.h

    r6795 r7664  
    11/*
    2  * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2008-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/stats.c

    r7463 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/stats.h

    r6998 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/torrent-cell-renderer.c

    r7069 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    114114
    115115    if( haveDown && haveUp )
    116         /* Translators: do not translate the "speed|" disambiguation prefix.
     116        /* Translators: "speed|" is here for disambiguation.  Please remove it from your translation.
    117117           %1$s is the download speed
    118118           %2$s is the upload speed */
     
    468468            my_bg.y = tmp_bg.y + tmp_bg.height;
    469469            my_cell.y = tmp_cell.y + tmp_cell.height;
    470             my_expose.y += tmp_expose.y + tmp_cell.height;
     470            my_expose.y = tmp_expose.y + tmp_cell.height;
    471471
    472472            g_free( str );
  • branches/1.5x/gtk/torrent-cell-renderer.h

    r6998 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/tr-core.c

    r7463 r7664  
    164164        GObjectClass * parent;
    165165
    166         pref_save( );
    167166        core->priv = NULL;
    168167
     
    450449    if( tr_ctorGetPeerLimit( ctor, TR_FORCE, NULL ) )
    451450        tr_ctorSetPeerLimit( ctor, TR_FORCE,
    452                             pref_int_get( PREF_KEY_MAX_PEERS_PER_TORRENT ) );
     451                             pref_int_get( TR_PREFS_KEY_PEER_LIMIT_TORRENT ) );
    453452
    454453    if( tr_ctorGetDownloadDir( ctor, TR_FORCE, NULL ) )
    455454    {
    456         const char * path = pref_string_get( PREF_KEY_DOWNLOAD_DIR );
     455        const char * path = pref_string_get( TR_PREFS_KEY_DOWNLOAD_DIR );
    457456        tr_ctorSetDownloadDir( ctor, TR_FORCE, path );
    458457    }
     
    584583        setSort( core, mode, isReversed );
    585584    }
    586     else if( !strcmp( key, PREF_KEY_MAX_PEERS_GLOBAL ) )
     585    else if( !strcmp( key, TR_PREFS_KEY_PEER_LIMIT_GLOBAL ) )
    587586    {
    588587        const uint16_t val = pref_int_get( key );
    589588        tr_sessionSetPeerLimit( tr_core_session( core ), val );
     589    }
     590    else if( !strcmp( key, TR_PREFS_KEY_PEER_LIMIT_TORRENT ) )
     591    {
     592        const uint16_t val = pref_int_get( key );
     593        tr_sessionSetPeerLimitPerTorrent( tr_core_session( core ), val );
    590594    }
    591595    else if( !strcmp( key, PREF_KEY_INHIBIT_HIBERNATION ) )
     
    684688    prefsChanged( core, PREF_KEY_SORT_REVERSED, NULL );
    685689    prefsChanged( core, PREF_KEY_DIR_WATCH_ENABLED, NULL );
    686     prefsChanged( core, PREF_KEY_MAX_PEERS_GLOBAL, NULL );
     690    prefsChanged( core, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, NULL );
    687691    prefsChanged( core, PREF_KEY_INHIBIT_HIBERNATION, NULL );
    688     g_signal_connect( core, "prefs-changed", G_CALLBACK(
    689                           prefsChanged ), NULL );
     692    g_signal_connect( core, "prefs-changed", G_CALLBACK( prefsChanged ), NULL );
    690693
    691694    return core;
     
    700703    {
    701704        core->priv->session = NULL;
     705        pref_save( session );
    702706        tr_sessionClose( session );
    703707    }
     
    819823        tr_ctorSetPaused( ctor, TR_FORCE, TRUE );
    820824    tr_ctorSetPeerLimit( ctor, TR_FALLBACK,
    821                         pref_int_get( PREF_KEY_MAX_PEERS_PER_TORRENT ) );
     825                         pref_int_get( TR_PREFS_KEY_PEER_LIMIT_TORRENT ) );
    822826
    823827    torrents = tr_sessionLoadTorrents ( tr_core_session( self ), ctor, &count );
     
    858862    if( filename && session )
    859863    {
    860         int       err;
    861         tr_ctor * ctor = tr_ctorNew( session );
     864        tr_ctor * ctor;
     865
     866        ctor = tr_ctorNew( session );
    862867        tr_core_apply_defaults( ctor );
    863868        tr_ctorSetPaused( ctor, TR_FORCE, !doStart );
     869
    864870        if( tr_ctorSetMetainfoFromFile( ctor, filename ) )
    865871        {
     
    867873            tr_ctorFree( ctor );
    868874        }
    869         else if( ( err = tr_torrentParse( session, ctor, NULL ) ) )
    870         {
    871             /* don't complain about .torrent files in the watch directory
    872                that have already been added... that gets annoying, and we
    873                don't want to nag about cleaning up the watch dir */
    874             const gboolean quiet = ( err == TR_EDUPLICATE )
    875                                 && ( core->priv->adding_from_watch_dir );
    876             if( !quiet )
    877                 tr_core_errsig( core, err, filename );
    878 
    879             tr_ctorFree( ctor );
    880         }
    881         else if( doPrompt )
    882             g_signal_emit( core, TR_CORE_GET_CLASS(
    883                                core )->promptsig, 0, ctor );
    884875        else
    885876        {
    886             tr_torrent * tor = tr_torrentNew( session, ctor, &err );
    887             if( err )
    888                 tr_core_errsig( core, err, filename );
    889             else
    890                 tr_core_add_torrent( core, tr_torrent_new_preexisting( tor ) );
     877            tr_info inf;
     878            int err = tr_torrentParse( session, ctor, &inf );
     879
     880            switch( err )
     881            {
     882                case TR_EINVALID:
     883                    tr_core_errsig( core, err, filename );
     884                    break;
     885
     886                case TR_EDUPLICATE:
     887                    /* don't complain about .torrent files in the watch directory
     888                     * that have already been added... that gets annoying and we
     889                     * don't want to be naggign users to clean up their watch dirs */
     890                    if( !core->priv->adding_from_watch_dir )
     891                        tr_core_errsig( core, err, inf.name );
     892                    tr_metainfoFree( &inf );
     893                    break;
     894
     895                default:
     896                    if( doPrompt )
     897                        g_signal_emit( core, TR_CORE_GET_CLASS( core )->promptsig, 0, ctor );
     898                    else {
     899                        tr_torrent * tor = tr_torrentNew( session, ctor, &err );
     900                        if( err )
     901                            tr_core_errsig( core, err, filename );
     902                        else
     903                            tr_core_add_torrent( core, tr_torrent_new_preexisting( tor ) );
     904                    }
     905                    tr_metainfoFree( &inf );
     906                    break;
     907            }
    891908        }
    892909    }
     
    900917{
    901918    add_filename( core, filename,
    902                  pref_flag_get( PREF_KEY_START ),
    903                  pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) );
     919                  pref_flag_get( PREF_KEY_START ),
     920                  pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) );
    904921    *success = TRUE;
    905922    return TRUE;
     
    12131230{
    12141231    g_signal_emit( core, TR_CORE_GET_CLASS( core )->prefsig, 0, key );
    1215     pref_save( );
     1232    pref_save( tr_core_session( core ) );
    12161233}
    12171234
  • branches/1.5x/gtk/tr-icon.c

    r7463 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/tr-prefs.c

    r7478 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    3636tr_prefs_init_global( void )
    3737{
    38     int          i;
    39     char         pw[32];
    4038    const char * str;
    41     const char * pool = "abcdefghijklmnopqrstuvwxyz"
    42                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    43                         "1234567890";
    44     GRand *      rand;
    4539
    4640    cf_check_older_configs( );
     
    4943    str = NULL;
    5044    if( !str ) str = g_get_user_special_dir( G_USER_DIRECTORY_DESKTOP );
    51     if( !str ) str = g_get_home_dir( );
     45    if( !str ) str = tr_getDefaultDownloadDir( );
    5246    pref_string_set_default ( PREF_KEY_DIR_WATCH, str );
    5347    pref_flag_set_default   ( PREF_KEY_DIR_WATCH_ENABLED, FALSE );
    5448#endif
    5549
    56     pref_int_set_default    ( PREF_KEY_PEER_SOCKET_TOS,
    57                               TR_DEFAULT_PEER_SOCKET_TOS );
    5850    pref_flag_set_default   ( PREF_KEY_INHIBIT_HIBERNATION, FALSE );
    59     pref_flag_set_default   ( PREF_KEY_BLOCKLIST_ENABLED, TRUE );
    6051    pref_flag_set_default   ( PREF_KEY_BLOCKLIST_UPDATES_ENABLED, TRUE );
    6152
    6253    pref_string_set_default ( PREF_KEY_OPEN_DIALOG_FOLDER, g_get_home_dir( ) );
    63 
    64     pref_int_set_default    ( PREF_KEY_MAX_PEERS_GLOBAL,
    65                               TR_DEFAULT_GLOBAL_PEER_LIMIT );
    66     pref_int_set_default    ( PREF_KEY_MAX_PEERS_PER_TORRENT, 50 );
    6754
    6855    pref_flag_set_default   ( PREF_KEY_TOOLBAR, TRUE );
     
    7259    pref_string_set_default ( PREF_KEY_STATUSBAR_STATS, "total-ratio" );
    7360
    74     pref_flag_set_default   ( PREF_KEY_DL_LIMIT_ENABLED, FALSE );
    75     pref_int_set_default    ( PREF_KEY_DL_LIMIT, 100 );
    76     pref_flag_set_default   ( PREF_KEY_UL_LIMIT_ENABLED, FALSE );
    77     pref_int_set_default    ( PREF_KEY_UL_LIMIT, 50 );
    7861    pref_flag_set_default   ( PREF_KEY_SCHED_LIMIT_ENABLED, FALSE );
    7962    pref_int_set_default    ( PREF_KEY_SCHED_BEGIN,    60 * 23 ); /* 11pm */
    8063    pref_int_set_default    ( PREF_KEY_SCHED_END,      60 * 7 );  /* 7am */
    81     pref_int_set_default    ( PREF_KEY_SCHED_DL_LIMIT, 200 );   /* 2x the other
    82                                                                   limit */
    83     pref_int_set_default    ( PREF_KEY_SCHED_UL_LIMIT, 100 );   /* 2x the other
    84                                                                   limit */
     64    pref_int_set_default    ( PREF_KEY_SCHED_DL_LIMIT, 200 );   /* 2x the other limit */
     65    pref_int_set_default    ( PREF_KEY_SCHED_UL_LIMIT, 100 );   /* 2x the other limit */
    8566
    8667    pref_flag_set_default   ( PREF_KEY_OPTIONS_PROMPT, TRUE );
     
    9071    pref_int_set_default    ( PREF_KEY_MAIN_WINDOW_X, 50 );
    9172    pref_int_set_default    ( PREF_KEY_MAIN_WINDOW_Y, 50 );
    92 
    93     pref_string_set_default ( PREF_KEY_PROXY_SERVER, "" );
    94     pref_int_set_default    ( PREF_KEY_PROXY_PORT, TR_DEFAULT_PROXY_PORT );
    95     pref_int_set_default    ( PREF_KEY_PROXY_TYPE, TR_DEFAULT_PROXY_TYPE );
    96     pref_flag_set_default   ( PREF_KEY_PROXY_SERVER_ENABLED,
    97                               TR_DEFAULT_PROXY_ENABLED );
    98     pref_flag_set_default   ( PREF_KEY_PROXY_AUTH_ENABLED,
    99                               TR_DEFAULT_PROXY_AUTH_ENABLED );
    100     pref_string_set_default ( PREF_KEY_PROXY_USERNAME, "" );
    101     pref_string_set_default ( PREF_KEY_PROXY_PASSWORD, "" );
     73    pref_string_set_default ( PREF_KEY_MAIN_WINDOW_LAYOUT_ORDER, "menu,toolbar,filter,list,statusbar" );
    10274
    10375    str = NULL;
     
    10678#endif
    10779    if( !str ) str = g_get_home_dir( );
    108     pref_string_set_default ( PREF_KEY_DOWNLOAD_DIR, str );
    109 
    110     pref_int_set_default    ( PREF_KEY_PORT, TR_DEFAULT_PORT );
    111 
    112     pref_flag_set_default   ( PREF_KEY_PORT_FORWARDING, TRUE );
    113     pref_flag_set_default   ( PREF_KEY_PEX, TR_DEFAULT_PEX_ENABLED );
     80    pref_string_set_default ( TR_PREFS_KEY_DOWNLOAD_DIR, str );
     81
    11482    pref_flag_set_default   ( PREF_KEY_ASKQUIT, TRUE );
    115     pref_flag_set_default   ( PREF_KEY_ENCRYPTION, TR_DEFAULT_ENCRYPTION );
    116     pref_flag_set_default   ( PREF_KEY_LAZY_BITFIELD,
    117                               TR_DEFAULT_LAZY_BITFIELD_ENABLED );
    118 
    119     pref_int_set_default    ( PREF_KEY_MSGLEVEL, TR_MSG_INF );
    12083
    12184    pref_string_set_default ( PREF_KEY_SORT_MODE, "sort-by-name" );
     
    12588    pref_flag_set_default   ( PREF_KEY_START, TRUE );
    12689    pref_flag_set_default   ( PREF_KEY_TRASH_ORIGINAL, FALSE );
    127 
    128     pref_flag_set_default   ( PREF_KEY_RPC_ENABLED, TR_DEFAULT_RPC_ENABLED );
    129     pref_int_set_default    ( PREF_KEY_RPC_PORT, TR_DEFAULT_RPC_PORT );
    130     pref_string_set_default ( PREF_KEY_RPC_WHITELIST, TR_DEFAULT_RPC_WHITELIST );
    131     pref_flag_set_default   ( PREF_KEY_RPC_WHITELIST_ENABLED,
    132                               TR_DEFAULT_RPC_WHITELIST_ENABLED  );
    133 
    134     rand = g_rand_new ( );
    135     for( i = 0; i < 16; ++i )
    136         pw[i] = pool[g_rand_int_range ( rand, 0, strlen( pool ) )];
    137     g_rand_free ( rand );
    138 
    139     pw[16] = '\0';
    140     pref_string_set_default( PREF_KEY_RPC_USERNAME, "transmission" );
    141     pref_string_set_default( PREF_KEY_RPC_PASSWORD, pw );
    142     pref_flag_set_default  ( PREF_KEY_RPC_AUTH_ENABLED, FALSE );
    143 
    144     pref_save( );
    14590}
    14691
     
    376321    hig_workarea_add_wide_control( t, &row, w );
    377322
    378     w = new_path_chooser_button( PREF_KEY_DOWNLOAD_DIR, core );
     323    w = new_path_chooser_button( TR_PREFS_KEY_DOWNLOAD_DIR, core );
    379324    hig_workarea_add_row( t, &row, _( "_Destination folder:" ), w, NULL );
    380325
     
    511456                    : TR_ENCRYPTION_PREFERRED;
    512457
    513     tr_core_set_pref_int( TR_CORE( core ), PREF_KEY_ENCRYPTION, val );
     458    tr_core_set_pref_int( TR_CORE( core ), TR_PREFS_KEY_ENCRYPTION, val );
    514459}
    515460
     
    531476    hig_workarea_add_section_title( t, &row, _( "Blocklist" ) );
    532477
    533     w = new_check_button( "", PREF_KEY_BLOCKLIST_ENABLED, core );
     478    w = new_check_button( "", TR_PREFS_KEY_BLOCKLIST_ENABLED, core );
    534479    updateBlocklistText( w, TR_CORE( core ) );
    535480    h = gtk_hbox_new( FALSE, GUI_PAD_BIG );
     
    554499    hig_workarea_add_section_title( t, &row, _( "Limits" ) );
    555500
    556     w = new_spin_button( PREF_KEY_MAX_PEERS_GLOBAL, core, 1, 3000, 5 );
     501    w = new_spin_button( TR_PREFS_KEY_PEER_LIMIT_GLOBAL, core, 1, 3000, 5 );
    557502    hig_workarea_add_row( t, &row, _( "Maximum peers _overall:" ), w, NULL );
    558     w = new_spin_button( PREF_KEY_MAX_PEERS_PER_TORRENT, core, 1, 300, 5 );
    559     hig_workarea_add_row( t, &row, _(
    560                               "Maximum peers per _torrent:" ), w, NULL );
     503    w = new_spin_button( TR_PREFS_KEY_PEER_LIMIT_TORRENT, core, 1, 300, 5 );
     504    hig_workarea_add_row( t, &row, _( "Maximum peers per _torrent:" ), w, NULL );
    561505
    562506    hig_workarea_add_section_divider( t, &row );
     
    566510    w = gtk_check_button_new_with_mnemonic( s );
    567511    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ),
    568                                   pref_int_get(
    569                                       PREF_KEY_ENCRYPTION ) ==
     512                                  pref_int_get( TR_PREFS_KEY_ENCRYPTION ) ==
    570513                                  TR_ENCRYPTION_REQUIRED );
    571514    g_signal_connect( w, "toggled", G_CALLBACK( onEncryptionToggled ), core );
     
    573516
    574517    s = _( "Use peer e_xchange" );
    575     w = new_check_button( s, PREF_KEY_PEX, core );
     518    w = new_check_button( s, TR_PREFS_KEY_PEX_ENABLED, core );
    576519    hig_workarea_add_wide_control( t, &row, w );
    577520
     
    649592    g_string_truncate( gstr, gstr->len - 1 ); /* remove the trailing comma */
    650593
    651     tr_core_set_pref( page->core, PREF_KEY_RPC_WHITELIST, gstr->str );
     594    tr_core_set_pref( page->core, TR_PREFS_KEY_RPC_WHITELIST, gstr->str );
    652595
    653596    g_string_free( gstr, TRUE );
     
    758701                  gpointer data UNUSED )
    759702{
    760     int    port = pref_int_get( PREF_KEY_RPC_PORT );
     703    int    port = pref_int_get( TR_PREFS_KEY_RPC_PORT );
    761704    char * url = g_strdup_printf( "http://localhost:%d/transmission/web",
    762705                                  port );
     
    785728    /* "enabled" checkbutton */
    786729    s = _( "_Enable web interface" );
    787     w = new_check_button( s, PREF_KEY_RPC_ENABLED, core );
     730    w = new_check_button( s, TR_PREFS_KEY_RPC_ENABLED, core );
    788731    page->rpc_tb = GTK_TOGGLE_BUTTON( w );
    789732    g_signal_connect( w, "clicked", G_CALLBACK( onRPCToggled ), page );
     
    797740
    798741    /* port */
    799     w = new_spin_button( PREF_KEY_RPC_PORT, core, 0, 65535, 1 );
     742    w = new_spin_button( TR_PREFS_KEY_RPC_PORT, core, 0, 65535, 1 );
    800743    page->widgets = g_slist_append( page->widgets, w );
    801744    w = hig_workarea_add_row( t, &row, _( "Listening _port:" ), w, NULL );
     
    804747    /* require authentication */
    805748    s = _( "_Require username" );
    806     w = new_check_button( s, PREF_KEY_RPC_AUTH_ENABLED, core );
     749    w = new_check_button( s, TR_PREFS_KEY_RPC_AUTH_REQUIRED, core );
    807750    hig_workarea_add_wide_control( t, &row, w );
    808751    page->auth_tb = GTK_TOGGLE_BUTTON( w );
     
    812755    /* username */
    813756    s = _( "_Username:" );
    814     w = new_entry( PREF_KEY_RPC_USERNAME, core );
     757    w = new_entry( TR_PREFS_KEY_RPC_USERNAME, core );
    815758    page->auth_widgets = g_slist_append( page->auth_widgets, w );
    816759    w = hig_workarea_add_row( t, &row, s, w, NULL );
     
    819762    /* password */
    820763    s = _( "Pass_word:" );
    821     w = new_entry( PREF_KEY_RPC_PASSWORD, core );
     764    w = new_entry( TR_PREFS_KEY_RPC_PASSWORD, core );
    822765    gtk_entry_set_visibility( GTK_ENTRY( w ), FALSE );
    823766    page->auth_widgets = g_slist_append( page->auth_widgets, w );
     
    827770    /* require authentication */
    828771    s = _( "Only allow the following IP _addresses to connect:" );
    829     w = new_check_button( s, PREF_KEY_RPC_WHITELIST_ENABLED, core );
     772    w = new_check_button( s, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, core );
    830773    hig_workarea_add_wide_control( t, &row, w );
    831774    page->whitelist_tb = GTK_TOGGLE_BUTTON( w );
     
    835778    /* access control list */
    836779    {
    837         const char *        val = pref_string_get( PREF_KEY_RPC_WHITELIST );
     780        const char *        val = pref_string_get( TR_PREFS_KEY_RPC_WHITELIST );
    838781        GtkTreeModel *      m = whitelist_tree_model_new( val );
    839782        GtkTreeViewColumn * c;
     
    920863{
    921864    GSList *       l;
    922     const gboolean proxy_enabled = pref_flag_get(
    923         PREF_KEY_PROXY_SERVER_ENABLED );
    924     const gboolean proxy_auth_enabled = pref_flag_get(
    925         PREF_KEY_PROXY_AUTH_ENABLED );
     865    const gboolean proxy_enabled = pref_flag_get( TR_PREFS_KEY_PROXY_ENABLED );
     866    const gboolean proxy_auth_enabled = pref_flag_get( TR_PREFS_KEY_PROXY_AUTH_ENABLED );
    926867
    927868    for( l = p->proxy_widgets; l != NULL; l = l->next )
     
    974915    {
    975916        struct ProxyPage * page = gpage;
    976         int                type = TR_PROXY_HTTP;
    977         gtk_tree_model_get( gtk_combo_box_get_model(
    978                                 w ), &iter, 1, &type, -1 );
    979         tr_core_set_pref_int( TR_CORE(
    980                                   page->core ), PREF_KEY_PROXY_TYPE, type );
     917        int type = TR_PROXY_HTTP;
     918        gtk_tree_model_get( gtk_combo_box_get_model( w ), &iter, 1, &type, -1 );
     919        tr_core_set_pref_int( TR_CORE( page->core ), TR_PREFS_KEY_PROXY_TYPE, type );
    981920    }
    982921}
     
    999938
    1000939    s = _( "Connect to tracker via a pro_xy" );
    1001     w = new_check_button( s, PREF_KEY_PROXY_SERVER_ENABLED, core );
     940    w = new_check_button( s, TR_PREFS_KEY_PROXY_ENABLED, core );
    1002941    g_signal_connect( w, "toggled", G_CALLBACK( onProxyToggled ), page );
    1003942    hig_workarea_add_wide_control( t, &row, w );
    1004943
    1005944    s = _( "Proxy _server:" );
    1006     w = new_entry( PREF_KEY_PROXY_SERVER, core );
     945    w = new_entry( TR_PREFS_KEY_PROXY, core );
    1007946    page->proxy_widgets = g_slist_append( page->proxy_widgets, w );
    1008947    w = hig_workarea_add_row( t, &row, s, w, NULL );
    1009948    page->proxy_widgets = g_slist_append( page->proxy_widgets, w );
    1010949
    1011     w = new_spin_button( PREF_KEY_PROXY_PORT, core, 0, 65535, 1 );
     950    w = new_spin_button( TR_PREFS_KEY_PROXY_PORT, core, 0, 65535, 1 );
    1012951    page->proxy_widgets = g_slist_append( page->proxy_widgets, w );
    1013952    w = hig_workarea_add_row( t, &row, _( "Proxy _port:" ), w, NULL );
     
    1019958    r = gtk_cell_renderer_text_new( );
    1020959    gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( w ), r, TRUE );
    1021     gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT(
    1022                                         w ), r, "text", 0, NULL );
    1023     gtk_combo_box_set_active( GTK_COMBO_BOX( w ),
    1024                              pref_int_get( PREF_KEY_PROXY_TYPE ) );
     960    gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT( w ), r, "text", 0, NULL );
     961    gtk_combo_box_set_active( GTK_COMBO_BOX( w ), pref_int_get( TR_PREFS_KEY_PROXY_TYPE ) );
    1025962    g_signal_connect( w, "changed", G_CALLBACK( onProxyTypeChanged ), page );
    1026963    g_object_unref( G_OBJECT( m ) );
     
    1030967
    1031968    s = _( "_Authentication is required" );
    1032     w = new_check_button( s, PREF_KEY_PROXY_AUTH_ENABLED, core );
     969    w = new_check_button( s, TR_PREFS_KEY_PROXY_AUTH_ENABLED, core );
    1033970    g_signal_connect( w, "toggled", G_CALLBACK( onProxyToggled ), page );
    1034971    hig_workarea_add_wide_control( t, &row, w );
     
    1036973
    1037974    s = _( "_Username:" );
    1038     w = new_entry( PREF_KEY_PROXY_USERNAME, core );
     975    w = new_entry( TR_PREFS_KEY_PROXY_USERNAME, core );
    1039976    page->proxy_auth_widgets = g_slist_append( page->proxy_auth_widgets, w );
    1040977    w = hig_workarea_add_row( t, &row, s, w, NULL );
     
    1042979
    1043980    s = _( "Pass_word:" );
    1044     w = new_entry( PREF_KEY_PROXY_PASSWORD, core );
     981    w = new_entry( TR_PREFS_KEY_RPC_PASSWORD, core );
    1045982    gtk_entry_set_visibility( GTK_ENTRY( w ), FALSE );
    1046983    page->proxy_auth_widgets = g_slist_append( page->proxy_auth_widgets, w );
     
    11661103
    11671104    s = _( "Limit _download speed (KB/s):" );
    1168     w = new_check_button( s, PREF_KEY_DL_LIMIT_ENABLED, core );
    1169     w2 = new_spin_button( PREF_KEY_DL_LIMIT, core, 0, INT_MAX, 5 );
    1170     gtk_widget_set_sensitive( GTK_WIDGET( w2 ),
    1171                              pref_flag_get( PREF_KEY_DL_LIMIT_ENABLED ) );
     1105    w = new_check_button( s, TR_PREFS_KEY_DSPEED_ENABLED, core );
     1106    w2 = new_spin_button( TR_PREFS_KEY_DSPEED, core, 0, INT_MAX, 5 );
     1107    gtk_widget_set_sensitive( GTK_WIDGET( w2 ), pref_flag_get( TR_PREFS_KEY_DSPEED_ENABLED ) );
    11721108    g_signal_connect( w, "toggled", G_CALLBACK( target_cb ), w2 );
    11731109    hig_workarea_add_row_w( t, &row, w, w2, NULL );
    11741110
    11751111    s = _( "Limit _upload speed (KB/s):" );
    1176     w = new_check_button( s, PREF_KEY_UL_LIMIT_ENABLED, core );
    1177     w2 = new_spin_button( PREF_KEY_UL_LIMIT, core, 0, INT_MAX, 5 );
    1178     gtk_widget_set_sensitive( GTK_WIDGET( w2 ),
    1179                              pref_flag_get( PREF_KEY_UL_LIMIT_ENABLED ) );
     1112    w = new_check_button( s, TR_PREFS_KEY_USPEED_ENABLED, core );
     1113    w2 = new_spin_button( TR_PREFS_KEY_USPEED, core, 0, INT_MAX, 5 );
     1114    gtk_widget_set_sensitive( GTK_WIDGET( w2 ), pref_flag_get( TR_PREFS_KEY_USPEED_ENABLED ) );
    11801115    g_signal_connect( w, "toggled", G_CALLBACK( target_cb ), w2 );
    11811116    hig_workarea_add_row_w( t, &row, w, w2, NULL );
     
    12021137    w = new_spin_button( PREF_KEY_SCHED_DL_LIMIT, core, 0, INT_MAX, 5 );
    12031138    page->sched_widgets = g_slist_append( page->sched_widgets, w );
    1204     l = hig_workarea_add_row( t, &row, _(
    1205                                   "Limit d_ownload speed (KB/s):" ), w,
    1206                               NULL );
     1139    l = hig_workarea_add_row( t, &row, _( "Limit d_ownload speed (KB/s):" ), w, NULL );
    12071140    page->sched_widgets = g_slist_append( page->sched_widgets, l );
    12081141
    12091142    w = new_spin_button( PREF_KEY_SCHED_UL_LIMIT, core, 0, INT_MAX, 5 );
    12101143    page->sched_widgets = g_slist_append( page->sched_widgets, w );
    1211     l = hig_workarea_add_row( t, &row, _(
    1212                                   "Limit u_pload speed (KB/s):" ), w, NULL );
     1144    l = hig_workarea_add_row( t, &row, _( "Limit u_pload speed (KB/s):" ), w, NULL );
    12131145    page->sched_widgets = g_slist_append( page->sched_widgets, l );
    12141146
     
    13001232                    gpointer      gdata )
    13011233{
    1302     if( !strcmp( key, PREF_KEY_PORT ) )
     1234    if( !strcmp( key, TR_PREFS_KEY_PEER_PORT ) )
    13031235    {
    13041236        struct network_page_data * ndata = gdata;
     
    13551287
    13561288    h = gtk_hbox_new( FALSE, GUI_PAD_BIG );
    1357     w2 = new_spin_button( PREF_KEY_PORT, core, 1, 65535, 1 );
     1289    w2 = new_spin_button( TR_PREFS_KEY_PEER_PORT, core, 1, 65535, 1 );
    13581290    gtk_box_pack_start( GTK_BOX( h ), w2, FALSE, FALSE, 0 );
    13591291    data->label = l = gtk_label_new( NULL );
     
    13651297    g_object_set_data( G_OBJECT( l ), "session",
    13661298                      tr_core_session( TR_CORE( core ) ) );
    1367     data->id = g_signal_connect( TR_CORE(
    1368                                      core ), "prefs-changed",
     1299    data->id = g_signal_connect( TR_CORE( core ), "prefs-changed",
    13691300                                 G_CALLBACK( onCorePrefsChanged ), data );
    1370     onCorePrefsChanged( NULL, PREF_KEY_PORT, data );
     1301    onCorePrefsChanged( NULL, TR_PREFS_KEY_PEER_PORT, data );
    13711302
    13721303    s = _( "Use UPnP or NAT-PMP port _forwarding from my router" );
    1373     w = new_check_button( s, PREF_KEY_PORT_FORWARDING, core );
     1304    w = new_check_button( s, TR_PREFS_KEY_PORT_FORWARDING, core );
    13741305    hig_workarea_add_wide_control( t, &row, w );
    13751306
  • branches/1.5x/gtk/tr-prefs.h

    r6870 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
     
    2222 * default in tr_prefs_init_global( void ) */
    2323
    24 #define PREF_KEY_DL_LIMIT_ENABLED       "download-limit-enabled"
    25 #define PREF_KEY_DL_LIMIT               "download-limit"
    26 #define PREF_KEY_UL_LIMIT_ENABLED       "upload-limit-enabled"
    27 #define PREF_KEY_UL_LIMIT               "upload-limit"
    28 #define PREF_KEY_SCHED_LIMIT_ENABLED    "sched-limit-enabled"
    29 #define PREF_KEY_SCHED_BEGIN            "sched-begin"
    30 #define PREF_KEY_SCHED_END              "sched-end"
    31 #define PREF_KEY_SCHED_DL_LIMIT         "sched-download-limit"
    32 #define PREF_KEY_SCHED_UL_LIMIT         "sched-upload-limit"
    33 #define PREF_KEY_OPTIONS_PROMPT         "show-options-window"
    34 #define PREF_KEY_DOWNLOAD_DIR           "download-dir"
    35 #define PREF_KEY_OPEN_DIALOG_FOLDER     "open-dialog-dir"
    36 #define PREF_KEY_INHIBIT_HIBERNATION    "inhibit-desktop-hibernation"
    37 #define PREF_KEY_DIR_WATCH              "watch-dir"
    38 #define PREF_KEY_DIR_WATCH_ENABLED      "watch-dir-enabled"
    39 #define PREF_KEY_SHOW_TRAY_ICON         "show-notification-area-icon"
    40 #define PREF_KEY_START                  "start-added-torrents"
    41 #define PREF_KEY_TRASH_ORIGINAL         "trash-original-torrent-files"
    42 #define PREF_KEY_PEER_SOCKET_TOS        "peer-socket-tos"
    43 #define PREF_KEY_PORT                   "peer-port"
    44 #define PREF_KEY_PORT_FORWARDING        "port-forwarding-enabled"
    45 #define PREF_KEY_PEX                    "pex-enabled"
    46 #define PREF_KEY_ASKQUIT                "prompt-before-exit"
    47 #define PREF_KEY_ENCRYPTION             "encryption"
    48 #define PREF_KEY_MSGLEVEL               "debug-message-level"
    49 #define PREF_KEY_LAZY_BITFIELD          "lazy-bitfield-enabled"
    50 #define PREF_KEY_SORT_MODE              "sort-mode"
    51 #define PREF_KEY_SORT_REVERSED          "sort-reversed"
    52 #define PREF_KEY_MINIMAL_VIEW           "minimal-view"
    53 #define PREF_KEY_FILTERBAR              "show-filterbar"
    54 #define PREF_KEY_STATUSBAR              "show-statusbar"
    55 #define PREF_KEY_STATUSBAR_STATS        "statusbar-stats"
    56 #define PREF_KEY_TOOLBAR                "show-toolbar"
    57 #define PREF_KEY_MAX_PEERS_GLOBAL       "max-peers-global"
    58 #define PREF_KEY_MAX_PEERS_PER_TORRENT  "max-peers-per-torrent"
    59 #define PREF_KEY_BLOCKLIST_ENABLED      "blocklist-enabled"
     24#define PREF_KEY_SCHED_LIMIT_ENABLED        "sched-limit-enabled"
     25#define PREF_KEY_SCHED_BEGIN                "sched-begin"
     26#define PREF_KEY_SCHED_END                  "sched-end"
     27#define PREF_KEY_SCHED_DL_LIMIT             "sched-download-limit"
     28#define PREF_KEY_SCHED_UL_LIMIT             "sched-upload-limit"
     29#define PREF_KEY_OPTIONS_PROMPT             "show-options-window"
     30#define PREF_KEY_OPEN_DIALOG_FOLDER         "open-dialog-dir"
     31#define PREF_KEY_INHIBIT_HIBERNATION        "inhibit-desktop-hibernation"
     32#define PREF_KEY_DIR_WATCH                  "watch-dir"
     33#define PREF_KEY_DIR_WATCH_ENABLED          "watch-dir-enabled"
     34#define PREF_KEY_SHOW_TRAY_ICON             "show-notification-area-icon"
     35#define PREF_KEY_START                      "start-added-torrents"
     36#define PREF_KEY_TRASH_ORIGINAL             "trash-original-torrent-files"
     37#define PREF_KEY_ASKQUIT                    "prompt-before-exit"
     38#define PREF_KEY_SORT_MODE                  "sort-mode"
     39#define PREF_KEY_SORT_REVERSED              "sort-reversed"
     40#define PREF_KEY_MINIMAL_VIEW               "minimal-view"
     41#define PREF_KEY_FILTERBAR                  "show-filterbar"
     42#define PREF_KEY_STATUSBAR                  "show-statusbar"
     43#define PREF_KEY_STATUSBAR_STATS            "statusbar-stats"
     44#define PREF_KEY_TOOLBAR                    "show-toolbar"
    6045#define PREF_KEY_BLOCKLIST_UPDATES_ENABLED  "blocklist-updates-enabled"
    61 #define PREF_KEY_MAIN_WINDOW_HEIGHT     "main-window-height"
    62 #define PREF_KEY_MAIN_WINDOW_WIDTH      "main-window-width"
    63 #define PREF_KEY_MAIN_WINDOW_X          "main-window-x"
    64 #define PREF_KEY_MAIN_WINDOW_Y          "main-window-y"
    65 #define PREF_KEY_RPC_PORT               "rpc-port"
    66 #define PREF_KEY_RPC_ENABLED            "rpc-enabled"
    67 #define PREF_KEY_RPC_WHITELIST          "rpc-whitelist"
    68 #define PREF_KEY_RPC_WHITELIST_ENABLED  "rpc-whitelist-enabled"
    69 #define PREF_KEY_RPC_AUTH_ENABLED       "rpc-authentication-required"
    70 #define PREF_KEY_RPC_PASSWORD           "rpc-password"
    71 #define PREF_KEY_RPC_USERNAME           "rpc-username"
    72 #define PREF_KEY_PROXY_SERVER           "proxy-server"
    73 #define PREF_KEY_PROXY_PORT             "proxy-port"
    74 #define PREF_KEY_PROXY_SERVER_ENABLED   "proxy-server-enabled"
    75 #define PREF_KEY_PROXY_TYPE             "proxy-type"
    76 #define PREF_KEY_PROXY_AUTH_ENABLED     "proxy-authentication-required"
    77 #define PREF_KEY_PROXY_USERNAME         "proxy-username"
    78 #define PREF_KEY_PROXY_PASSWORD         "proxy-authentication"
    79 
     46#define PREF_KEY_MAIN_WINDOW_LAYOUT_ORDER   "main-window-layout-order"
     47#define PREF_KEY_MAIN_WINDOW_HEIGHT         "main-window-height"
     48#define PREF_KEY_MAIN_WINDOW_WIDTH          "main-window-width"
     49#define PREF_KEY_MAIN_WINDOW_X              "main-window-x"
     50#define PREF_KEY_MAIN_WINDOW_Y              "main-window-y"
    8051
    8152void tr_prefs_init_global( void );
  • branches/1.5x/gtk/tr-torrent.c

    r6978 r7664  
    167167                             void *             user_data )
    168168{
    169     if( completeness == TR_CP_COMPLETE )
     169    if( completeness != TR_LEECH )
    170170        g_idle_add( notifyInMainThread, user_data );
    171171}
     
    319319tr_torrent_delete_files( TrTorrent * gtor )
    320320{
    321     tr_file_index_t i;
    322     const tr_info * info = tr_torrent_info( gtor );
    323     const char *    stop =
    324         tr_torrentGetDownloadDir( tr_torrent_handle( gtor ) );
    325 
    326     for( i = 0; info && i < info->fileCount; ++i )
    327     {
    328         char * file = g_build_filename( stop, info->files[i].name, NULL );
    329         while( strcmp( stop, file ) && strlen( stop ) < strlen( file ) )
    330         {
    331             char * swap = g_path_get_dirname( file );
    332             tr_file_trash_or_unlink( file );
    333             g_free( file );
    334             file = swap;
    335         }
    336 
    337         g_free( file );
    338     }
     321    tr_torrentDeleteLocalData( tr_torrent_handle( gtor ), tr_file_trash_or_unlink );
    339322}
    340323
  • branches/1.5x/gtk/tr-window.c

    r7260 r7664  
    129129                    gpointer            user_data UNUSED )
    130130{
    131     action_activate( "show-torrent-details" );
     131    action_activate( "show-torrent-properties" );
    132132}
    133133
     
    499499
    500500GtkWidget *
    501 tr_window_new( GtkUIManager * ui_manager,
    502                TrCore *       core )
     501tr_window_new( GtkUIManager * ui_mgr, TrCore * core )
    503502{
    504503    int           i, n;
    505504    const char *  pch;
    506505    PrivateData * p;
     506    GtkWidget   *mainmenu, *toolbar, *filter, *list, *status;
    507507    GtkWidget *   vbox, *w, *self, *h, *c, *s, *image, *menu;
    508508    GtkWindow *   win;
    509509    GSList *      l;
    510510    GSList *      toggles;
     511
    511512    const char *  filter_names[FILTER_MODE_QTY] = {
    512513        /* show all torrents */
     
    538539    gtk_window_set_role( win, "tr-main" );
    539540    gtk_window_set_default_size( win,
    540                                 pref_int_get( PREF_KEY_MAIN_WINDOW_WIDTH ),
    541                                 pref_int_get( PREF_KEY_MAIN_WINDOW_HEIGHT ) );
     541                                 pref_int_get( PREF_KEY_MAIN_WINDOW_WIDTH ),
     542                                 pref_int_get( PREF_KEY_MAIN_WINDOW_HEIGHT ) );
    542543    gtk_window_move( win, pref_int_get( PREF_KEY_MAIN_WINDOW_X ),
    543                     pref_int_get( PREF_KEY_MAIN_WINDOW_Y ) );
    544     gtk_window_add_accel_group( win,
    545                                gtk_ui_manager_get_accel_group( ui_manager ) );
     544                     pref_int_get( PREF_KEY_MAIN_WINDOW_Y ) );
     545    gtk_window_add_accel_group( win, gtk_ui_manager_get_accel_group( ui_mgr ) );
    546546
    547547    /* window's main container */
     
    550550
    551551    /* main menu */
    552     w = action_get_widget( "/main-window-menu" );
    553     gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
     552    w = mainmenu = action_get_widget( "/main-window-menu" );
    554553    w = action_get_widget( "/main-window-menu/torrent-menu/update-tracker" );
    555554#if GTK_CHECK_VERSION( 2, 12, 0 )
     
    559558
    560559    /* toolbar */
    561     w = p->toolbar = action_get_widget( "/main-window-toolbar" );
    562     gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
     560    w = toolbar = p->toolbar = action_get_widget( "/main-window-toolbar" );
    563561
    564562    /* filter */
    565563    toggles = NULL;
    566     h = p->filter = gtk_hbox_new( FALSE, 0 );
     564    h = filter = p->filter = gtk_hbox_new( FALSE, 0 );
    567565    gtk_container_set_border_width( GTK_CONTAINER( h ), GUI_PAD_SMALL );
    568566    for( i = 0; i < FILTER_MODE_QTY; ++i )
     
    591589                                        TRUE );
    592590    gtk_box_pack_end( GTK_BOX( h ), s, FALSE, FALSE, 0 );
    593     gtk_box_pack_start( GTK_BOX( vbox ), h, FALSE, FALSE, 0 );
    594591    g_signal_connect( s, "changed", G_CALLBACK( filter_entry_changed ), p );
    595 
    596     w = gtk_hseparator_new( );
    597     gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
    598592
    599593    /* status menu */
     
    618612
    619613    /* status */
    620     h = p->status = gtk_hbox_new( FALSE, GUI_PAD );
     614    h = status = p->status = gtk_hbox_new( FALSE, GUI_PAD );
    621615    gtk_container_set_border_width( GTK_CONTAINER( h ), GUI_PAD );
    622616    w = p->gutter_lb = gtk_label_new( "N Torrents" );
     
    645639    g_signal_connect( w, "button-release-event",
    646640                      G_CALLBACK( onYinYangReleased ), p );
    647     gtk_box_pack_start( GTK_BOX( vbox ), h, FALSE, FALSE, 0 );
    648641
    649642    menu = gtk_menu_new( );
     
    654647        GtkWidget *  w = gtk_radio_menu_item_new_with_label ( l, name );
    655648        l = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM( w ) );
    656         g_object_set_data( G_OBJECT(
    657                               w ), FILTER_TEXT_MODE_KEY, GINT_TO_POINTER( i ) );
    658         g_signal_connect( w, "toggled", G_CALLBACK(
    659                               filter_text_toggled_cb ), p );
     649        g_object_set_data( G_OBJECT( w ), FILTER_TEXT_MODE_KEY,
     650                           GINT_TO_POINTER( i ) );
     651        g_signal_connect( w, "toggled",
     652                          G_CALLBACK( filter_text_toggled_cb ), p );
    660653        gtk_menu_shell_append( GTK_MENU_SHELL( menu ), w );
    661654        gtk_widget_show( w );
    662655    }
    663     g_signal_connect( s, "icon-released", G_CALLBACK(
    664                           entry_icon_released ), menu );
     656    g_signal_connect( s, "icon-released",
     657                      G_CALLBACK( entry_icon_released ), menu );
    665658
    666659    /* workarea */
    667660    p->view = makeview( p, core );
    668     w = p->scroll = gtk_scrolled_window_new( NULL, NULL );
    669     gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(
    670                                         w ), GTK_POLICY_NEVER,
    671                                     GTK_POLICY_AUTOMATIC );
    672     gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(
    673                                              w ), GTK_SHADOW_IN );
     661    w = list = p->scroll = gtk_scrolled_window_new( NULL, NULL );
     662    gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( w ),
     663                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
     664    gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( w ),
     665                                         GTK_SHADOW_IN );
    674666    gtk_container_add( GTK_CONTAINER( w ), p->view );
    675     gtk_box_pack_start( GTK_BOX( vbox ), w, TRUE, TRUE, 0 );
    676     gtk_container_set_focus_child( GTK_CONTAINER( vbox ), w );
     667
     668    /* layout the widgets */
     669    {
     670        const char * str = pref_string_get( PREF_KEY_MAIN_WINDOW_LAYOUT_ORDER );
     671        char ** tokens = g_strsplit( str, ",", -1 );
     672        for( i=0; tokens && tokens[i]; ++i )
     673        {
     674            const char * key = tokens[i];
     675
     676            if( !strcmp( key, "menu" ) )
     677                gtk_box_pack_start( GTK_BOX( vbox ), mainmenu, FALSE, FALSE, 0 );
     678            else if( !strcmp( key, "toolbar" ) )
     679                gtk_box_pack_start( GTK_BOX( vbox ), toolbar, FALSE, FALSE, 0 );
     680            else if( !strcmp( key, "filter" ) )
     681                gtk_box_pack_start( GTK_BOX( vbox ), filter, FALSE, FALSE, 0 );
     682            else if( !strcmp( key, "list" ) )
     683                gtk_box_pack_start( GTK_BOX( vbox ), list, TRUE, TRUE, 0 );
     684            else if( !strcmp( key, "statusbar" ) )
     685                gtk_box_pack_start( GTK_BOX( vbox ), status, FALSE, FALSE, 0 );
     686        }
     687        g_strfreev( tokens );
     688    }
    677689
    678690    /* show all but the window */
     
    740752        tr_strlsize( up, stats.uploadedBytes, sizeof( up ) );
    741753        tr_strlsize( down, stats.downloadedBytes, sizeof( down ) );
    742         /* Translators: do not translate the "size|" disambiguation prefix.
     754        /* Translators: "size|" is here for disambiguation.  Please remove it from your translation.
    743755           %1$s is the size of the data we've downloaded
    744756           %2$s is the size of the data we've uploaded */
     
    751763        tr_strlsize( up, stats.uploadedBytes, sizeof( up ) );
    752764        tr_strlsize( down, stats.downloadedBytes, sizeof( down ) );
    753         /* Translators: do not translate the "size|" disambiguation prefix.
     765        /* Translators: "size|" is here for disambiguation.  Please remove it from your translation.
    754766           %1$s is the size of the data we've downloaded
    755767           %2$s is the size of the data we've uploaded */
  • branches/1.5x/gtk/tracker-list.c

    r7463 r7664  
    11/*
    2  * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
     2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
    33 *
    44 * This file is licensed by the GPL version 2.  Works owned by the
  • branches/1.5x/gtk/ui.h

    r6870 r7664  
    66    "      <menuitem action='new-torrent'/>\n"
    77    "      <separator/>\n"
    8     "      <menuitem action='show-torrent-details'/>\n"
     8    "      <menuitem action='show-torrent-properties'/>\n"
    99    "      <menuitem action='open-torrent-folder'/>\n"
    1010    "      <separator/>\n"
     
    5656    "    <toolitem action='remove-torrent'/>\n"
    5757    "    <separator/>\n"
    58     "    <toolitem action='show-torrent-details'/>\n"
     58    "    <toolitem action='show-torrent-properties'/>\n"
    5959    "  </toolbar>\n"
    6060    "\n"
    6161    "  <popup name='main-window-popup'>\n"
    62     "    <menuitem action='show-torrent-details'/>\n"
     62    "    <menuitem action='show-torrent-properties'/>\n"
    6363    "    <menuitem action='open-torrent-folder'/>\n"
    6464    "    <separator/>\n"
     
    7979    "    <menuitem action='show-about-dialog'/>\n"
    8080    "    <separator/>\n"
     81    "    <menuitem action='pause-all-torrents'/>\n"
     82    "    <separator/>\n"
    8183    "    <menuitem action='quit'/>\n"
    8284    "  </popup>\n"
  • branches/1.5x/gtk/util.c

    r7463 r7664  
    515515}
    516516
    517 void
     517int
    518518tr_file_trash_or_unlink( const char * filename )
    519519{
     
    522522        gboolean trashed = FALSE;
    523523#ifdef HAVE_GIO
    524         GError * err = NULL;
    525524        GFile *  file = g_file_new_for_path( filename );
    526         trashed = g_file_trash( file, NULL, &err );
     525        trashed = g_file_trash( file, NULL, NULL );
    527526        g_object_unref( G_OBJECT( file ) );
    528527#endif
     
    530529            g_unlink( filename );
    531530    }
     531
     532    return 0;
    532533}
    533534
  • branches/1.5x/gtk/util.h

    r7463 r7664  
    133133gpointer    tr_object_ref_sink( gpointer object );
    134134
    135 void        tr_file_trash_or_unlink( const char * filename );
     135int         tr_file_trash_or_unlink( const char * filename );
    136136
    137137#endif /* GTK_MAJOR_VERSION */
  • branches/1.5x/libtransmission/ConvertUTF.c

    r6795 r7664  
    11/*
    22 * Copyright 2001-2004 Unicode, Inc.
    3  *
     3 * 
    44 * Disclaimer
    5  *
     5 * 
    66 * This source code is provided as is by Unicode, Inc. No claims are
    77 * made as to fitness for any particular purpose. No warranties of any
     
    1111 * sole remedy for any claim will be exchange of defective media
    1212 * within 90 days of receipt.
    13  *
     13 * 
    1414 * Limitations on Rights to Redistribute This Code
    15  *
     15 * 
    1616 * Unicode, Inc. hereby grants the right to freely use the information
    1717 * supplied in this file in the creation of products supporting the
     
    2727    Rev History: Rick McGowan, fixes & updates May 2001.
    2828    Sept 2001: fixed const & error conditions per
    29     mods suggested by S. Parent & A. Lillich.
     29        mods suggested by S. Parent & A. Lillich.
    3030    June 2002: Tim Dodd added detection and handling of incomplete
    31     source sequences, enhanced error detection, added casts
    32     to eliminate compiler warnings.
     31        source sequences, enhanced error detection, added casts
     32        to eliminate compiler warnings.
    3333    July 2003: slight mods to back out aggressive FFFE detection.
    3434    Jan 2004: updated switches in from-UTF8 conversions.
    3535    Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
     36    May 2006: updated isLegalUTF8Sequence.
    3637
    3738    See the header file "ConvertUTF.h" for complete documentation.
    3839
    39    ------------------------------------------------------------------------ */
    40 
    41 
    42 #include "ConvertUTF.h"
     40------------------------------------------------------------------------ */
     41
    4342#ifdef CVTUTF_DEBUG
    4443 #include <stdio.h>
    4544#endif
    46 
    47 static const int   halfShift  = 10; /* used for shifting by 10 bits */
     45#include <string.h> /* strlen() */
     46#include <unistd.h> /* ssize_t */
     47#include "ConvertUTF.h"
     48
     49static const int halfShift  = 10; /* used for shifting by 10 bits */
    4850
    4951static const UTF32 halfBase = 0x0010000UL;
     
    5456#define UNI_SUR_LOW_START   (UTF32)0xDC00
    5557#define UNI_SUR_LOW_END     (UTF32)0xDFFF
    56 #define false      0
    57 #define true        1
    58 
    59 /* --------------------------------------------------------------------- */
    60 
    61 ConversionResult
    62 ConvertUTF32toUTF16( const UTF32**   sourceStart,
    63                      const UTF32*    sourceEnd,
    64                      UTF16**         targetStart,
    65                      UTF16*          targetEnd,
    66                      ConversionFlags flags )
    67 {
     58#define false      0
     59#define true        1
     60
     61/* --------------------------------------------------------------------- */
     62
     63ConversionResult ConvertUTF32toUTF16 (
     64        const UTF32** sourceStart, const UTF32* sourceEnd,
     65        UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
    6866    ConversionResult result = conversionOK;
    69     const UTF32*     source = *sourceStart;
    70     UTF16*           target = *targetStart;
    71 
    72     while( source < sourceEnd )
    73     {
    74         UTF32 ch;
    75         if( target >= targetEnd )
    76         {
    77             result = targetExhausted; break;
    78         }
    79         ch = *source++;
    80         if( ch <= UNI_MAX_BMP ) /* Target is a character <= 0xFFFF */
    81         { /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are
    82             both reserved values */
    83             if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END )
    84             {
    85                 if( flags == strictConversion )
    86                 {
    87                     --source; /* return to the illegal value itself */
    88                     result = sourceIllegal;
    89                     break;
    90                 }
    91                 else
    92                 {
    93                     *target++ = UNI_REPLACEMENT_CHAR;
    94                 }
    95             }
    96             else
    97             {
    98                 *target++ = (UTF16)ch; /* normal case */
    99             }
    100         }
    101         else if( ch > UNI_MAX_LEGAL_UTF32 )
    102         {
    103             if( flags == strictConversion )
    104             {
    105                 result = sourceIllegal;
    106             }
    107             else
    108             {
    109                 *target++ = UNI_REPLACEMENT_CHAR;
    110             }
    111         }
    112         else
    113         {
    114             /* target is a character in range 0xFFFF - 0x10FFFF. */
    115             if( target + 1 >= targetEnd )
    116             {
    117                 --source; /* Back up source pointer! */
    118                 result = targetExhausted; break;
    119             }
    120             ch -= halfBase;
    121             *target++ = (UTF16)( ( ch >> halfShift ) + UNI_SUR_HIGH_START );
    122             *target++ = (UTF16)( ( ch & halfMask ) + UNI_SUR_LOW_START );
    123         }
    124     }
    125 
     67    const UTF32* source = *sourceStart;
     68    UTF16* target = *targetStart;
     69    while (source < sourceEnd) {
     70        UTF32 ch;
     71        if (target >= targetEnd) {
     72            result = targetExhausted; break;
     73        }
     74        ch = *source++;
     75        if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
     76            /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
     77            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
     78                if (flags == strictConversion) {
     79                    --source; /* return to the illegal value itself */
     80                    result = sourceIllegal;
     81                    break;
     82                } else {
     83                    *target++ = UNI_REPLACEMENT_CHAR;
     84                }
     85            } else {
     86                *target++ = (UTF16)ch; /* normal case */
     87            }
     88        } else if (ch > UNI_MAX_LEGAL_UTF32) {
     89            if (flags == strictConversion) {
     90                result = sourceIllegal;
     91            } else {
     92                *target++ = UNI_REPLACEMENT_CHAR;
     93            }
     94        } else {
     95            /* target is a character in range 0xFFFF - 0x10FFFF. */
     96            if (target + 1 >= targetEnd) {
     97                --source; /* Back up source pointer! */
     98                result = targetExhausted; break;
     99            }
     100            ch -= halfBase;
     101            *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
     102            *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
     103        }
     104    }
    126105    *sourceStart = source;
    127106    *targetStart = target;
     
    131110/* --------------------------------------------------------------------- */
    132111
    133 ConversionResult
    134 ConvertUTF16toUTF32( const UTF16**   sourceStart,
    135                      const UTF16*    sourceEnd,
    136                      UTF32**         targetStart,
    137                      UTF32*          targetEnd,
    138                      ConversionFlags flags )
    139 {
     112ConversionResult ConvertUTF16toUTF32 (
     113        const UTF16** sourceStart, const UTF16* sourceEnd,
     114        UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
    140115    ConversionResult result = conversionOK;
    141     const UTF16*     source = *sourceStart;
    142     UTF32*           target = *targetStart;
    143     UTF32            ch, ch2;
    144 
    145     while( source < sourceEnd )
    146     {
    147         const UTF16* oldSource = source; /*  In case we have to back up because
    148                                            of target overflow. */
    149         ch = *source++;
    150         /* If we have a surrogate pair, convert to UTF32 first. */
    151         if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END )
    152         {
    153             /* If the 16 bits following the high surrogate are in the source
    154               buffer... */
    155             if( source < sourceEnd )
    156             {
    157                 ch2 = *source;
    158                 /* If it's a low surrogate, convert to UTF32. */
    159                 if( ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END )
    160                 {
    161                     ch = ( ( ch - UNI_SUR_HIGH_START ) << halfShift )
    162                          + ( ch2 - UNI_SUR_LOW_START ) + halfBase;
    163                     ++source;
    164                 }
    165                 else if( flags == strictConversion ) /* it's an unpaired high
    166                                                        surrogate */
    167                 {
    168                     --source; /* return to the illegal value itself */
    169                     result = sourceIllegal;
    170                     break;
    171                 }
    172             }
    173             else /* We don't have the 16 bits following the high surrogate. */
    174             {
    175                 --source; /* return to the high surrogate */
    176                 result = sourceExhausted;
    177                 break;
    178             }
    179         }
    180         else if( flags == strictConversion )
    181         {
    182             /* UTF-16 surrogate values are illegal in UTF-32 */
    183             if( ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END )
    184             {
    185                 --source; /* return to the illegal value itself */
    186                 result = sourceIllegal;
    187                 break;
    188             }
    189         }
    190         if( target >= targetEnd )
    191         {
    192             source = oldSource; /* Back up source pointer! */
    193             result = targetExhausted; break;
    194         }
    195         *target++ = ch;
    196     }
    197 
     116    const UTF16* source = *sourceStart;
     117    UTF32* target = *targetStart;
     118    UTF32 ch, ch2;
     119    while (source < sourceEnd) {
     120        const UTF16* oldSource = source; /*  In case we have to back up because of target overflow. */
     121        ch = *source++;
     122        /* If we have a surrogate pair, convert to UTF32 first. */
     123        if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
     124            /* If the 16 bits following the high surrogate are in the source buffer... */
     125            if (source < sourceEnd) {
     126                ch2 = *source;
     127                /* If it's a low surrogate, convert to UTF32. */
     128                if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
     129                    ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
     130                        + (ch2 - UNI_SUR_LOW_START) + halfBase;
     131                    ++source;
     132                } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
     133                    --source; /* return to the illegal value itself */
     134                    result = sourceIllegal;
     135                    break;
     136                }
     137            } else { /* We don't have the 16 bits following the high surrogate. */
     138                --source; /* return to the high surrogate */
     139                result = sourceExhausted;
     140                break;
     141            }
     142        } else if (flags == strictConversion) {
     143            /* UTF-16 surrogate values are illegal in UTF-32 */
     144            if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
     145                --source; /* return to the illegal value itself */
     146                result = sourceIllegal;
     147                break;
     148            }
     149        }
     150        if (target >= targetEnd) {
     151            source = oldSource; /* Back up source pointer! */
     152            result = targetExhausted; break;
     153        }
     154        *target++ = ch;
     155    }
    198156    *sourceStart = source;
    199157    *targetStart = target;
    200158#ifdef CVTUTF_DEBUG
    201     if( result == sourceIllegal )
    202     {
    203         fprintf( stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n",
    204                  ch,
    205                  ch2 );
    206         fflush( stderr );
    207     }
     159if (result == sourceIllegal) {
     160    fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
     161    fflush(stderr);
     162}
    208163#endif
    209164    return result;
     
    219174 * allowed in earlier algorithms.
    220175 */
    221 static const char  trailingBytesForUTF8[256] = {
    222     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    223     0, 0, 0, 0, 0, 0, 0, 0,
    224     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    225     0, 0, 0, 0, 0, 0, 0, 0,
    226     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    227     0, 0, 0, 0, 0, 0, 0, 0,
    228     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    229     0, 0, 0, 0, 0, 0, 0, 0,
    230     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    231     0, 0, 0, 0, 0, 0, 0, 0,
    232     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    233     0, 0, 0, 0, 0, 0, 0, 0,
    234     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    235     1, 1, 1, 1, 1, 1, 1, 1,
    236     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
    237     4, 4, 4, 4, 5, 5, 5, 5
     176static const char trailingBytesForUTF8[256] = {
     177    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     178    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     179    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     180    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     181    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     182    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     183    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
     184    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
    238185};
    239186
     
    243190 * in a UTF-8 sequence.
    244191 */
    245 static const UTF32 offsetsFromUTF8[6] =
    246 { 0x00000000UL,                                           0x00003080UL,
    247   0x000E2080UL,
    248   0x03C82080UL, 0xFA082080UL,
    249   0x82082080UL };
     192static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
     193                     0x03C82080UL, 0xFA082080UL, 0x82082080UL };
    250194
    251195/*
     
    256200 * for *legal* UTF-8 will be 4 or fewer bytes total.
    257201 */
    258 static const UTF8  firstByteMark[7] =
    259 { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
     202static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
    260203
    261204/* --------------------------------------------------------------------- */
     
    271214/* --------------------------------------------------------------------- */
    272215
    273 ConversionResult
    274 ConvertUTF16toUTF8( const UTF16**   sourceStart,
    275                     const UTF16*    sourceEnd,
    276                     UTF8**          targetStart,
    277                     UTF8*           targetEnd,
    278                     ConversionFlags flags )
    279 {
     216ConversionResult ConvertUTF16toUTF8 (
     217        const UTF16** sourceStart, const UTF16* sourceEnd,
     218        UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
    280219    ConversionResult result = conversionOK;
    281     const UTF16*     source = *sourceStart;
    282     UTF8*            target = *targetStart;
    283 
    284     while( source < sourceEnd )
    285     {
    286         UTF32          ch;
    287         unsigned short bytesToWrite = 0;
    288         const UTF32    byteMask = 0xBF;
    289         const UTF32    byteMark = 0x80;
    290         const UTF16*   oldSource = source; /* In case we have to back up because
    291                                              of target overflow. */
    292         ch = *source++;
    293         /* If we have a surrogate pair, convert to UTF32 first. */
    294         if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END )
    295         {
    296             /* If the 16 bits following the high surrogate are in the source
    297               buffer... */
    298             if( source < sourceEnd )
    299             {
    300                 UTF32 ch2 = *source;
    301                 /* If it's a low surrogate, convert to UTF32. */
    302                 if( ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END )
    303                 {
    304                     ch = ( ( ch - UNI_SUR_HIGH_START ) << halfShift )
    305                          + ( ch2 - UNI_SUR_LOW_START ) + halfBase;
    306                     ++source;
    307                 }
    308                 else if( flags == strictConversion ) /* it's an unpaired high
    309                                                        surrogate */
    310                 {
    311                     --source; /* return to the illegal value itself */
    312                     result = sourceIllegal;
    313                     break;
    314                 }
    315             }
    316             else /* We don't have the 16 bits following the high surrogate. */
    317             {
    318                 --source; /* return to the high surrogate */
    319                 result = sourceExhausted;
    320                 break;
    321             }
    322         }
    323         else if( flags == strictConversion )
    324         {
    325             /* UTF-16 surrogate values are illegal in UTF-32 */
    326             if( ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END )
    327             {
    328                 --source; /* return to the illegal value itself */
    329                 result = sourceIllegal;
    330                 break;
    331             }
    332         }
    333         /* Figure out how many bytes the result will require */
    334         if( ch < (UTF32)0x80 )
    335         {
    336             bytesToWrite = 1;
    337         }
    338         else if( ch < (UTF32)0x800 )
    339         {
    340             bytesToWrite = 2;
    341         }
    342         else if( ch < (UTF32)0x10000 )
    343         {
    344             bytesToWrite = 3;
    345         }
    346         else if( ch < (UTF32)0x110000 )
    347         {
    348             bytesToWrite = 4;
    349         }
    350         else
    351         {
    352             bytesToWrite = 3;
    353             ch = UNI_REPLACEMENT_CHAR;
    354         }
    355 
    356         target += bytesToWrite;
    357         if( target > targetEnd )
    358         {
    359             source = oldSource; /* Back up source pointer! */
    360             target -= bytesToWrite; result = targetExhausted; break;
    361         }
    362         switch( bytesToWrite ) /* note: everything falls through. */
    363         {
    364             case 4:
    365                 *--target =
    366                     (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
    367 
    368             case 3:
    369                 *--target =
    370                     (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
    371 
    372             case 2:
    373                 *--target =
    374                     (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
    375 
    376             case 1:
    377                 *--target =  (UTF8)( ch | firstByteMark[bytesToWrite] );
    378         }
    379         target += bytesToWrite;
    380     }
    381 
     220    const UTF16* source = *sourceStart;
     221    UTF8* target = *targetStart;
     222    while (source < sourceEnd) {
     223        UTF32 ch;
     224        unsigned short bytesToWrite = 0;
     225        const UTF32 byteMask = 0xBF;
     226        const UTF32 byteMark = 0x80;
     227        const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
     228        ch = *source++;
     229        /* If we have a surrogate pair, convert to UTF32 first. */
     230        if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
     231            /* If the 16 bits following the high surrogate are in the source buffer... */
     232            if (source < sourceEnd) {
     233                UTF32 ch2 = *source;
     234                /* If it's a low surrogate, convert to UTF32. */
     235                if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
     236                    ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
     237                        + (ch2 - UNI_SUR_LOW_START) + halfBase;
     238                    ++source;
     239                } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
     240                    --source; /* return to the illegal value itself */
     241                    result = sourceIllegal;
     242                    break;
     243                }
     244            } else { /* We don't have the 16 bits following the high surrogate. */
     245                --source; /* return to the high surrogate */
     246                result = sourceExhausted;
     247                break;
     248            }
     249        } else if (flags == strictConversion) {
     250            /* UTF-16 surrogate values are illegal in UTF-32 */
     251            if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
     252                --source; /* return to the illegal value itself */
     253                result = sourceIllegal;
     254                break;
     255            }
     256        }
     257        /* Figure out how many bytes the result will require */
     258        if (ch < (UTF32)0x80) {      bytesToWrite = 1;
     259        } else if (ch < (UTF32)0x800) {     bytesToWrite = 2;
     260        } else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;
     261        } else if (ch < (UTF32)0x110000) {  bytesToWrite = 4;
     262        } else {                            bytesToWrite = 3;
     263                                            ch = UNI_REPLACEMENT_CHAR;
     264        }
     265
     266        target += bytesToWrite;
     267        if (target > targetEnd) {
     268            source = oldSource; /* Back up source pointer! */
     269            target -= bytesToWrite; result = targetExhausted; break;
     270        }
     271        switch (bytesToWrite) { /* note: everything falls through. */
     272            case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
     273            case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
     274            case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
     275            case 1: *--target =  (UTF8)(ch | firstByteMark[bytesToWrite]);
     276        }
     277        target += bytesToWrite;
     278    }
    382279    *sourceStart = source;
    383280    *targetStart = target;
     
    398295 */
    399296
    400 static Boolean
    401 isLegalUTF8( const UTF8 *source,
    402              int         length )
    403 {
    404     UTF8        a;
    405     const UTF8 *srcptr = source + length;
    406 
    407     switch( length )
    408     {
    409         default:
    410             return false;
    411 
    412         /* Everything else falls through when "true"... */
    413         case 4:
    414             if( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return false;
    415 
    416         case 3:
    417             if( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return false;
    418 
    419         case 2:
    420             if( ( a = ( *--srcptr ) ) > 0xBF ) return false;
    421 
    422             switch( *source )
    423             {
    424                 /* no fall-through in this inner switch */
    425                 case 0xE0:
    426                     if( a < 0xA0 ) return false;break;
    427 
    428                 case 0xED:
    429                     if( a > 0x9F ) return false;break;
    430 
    431                 case 0xF0:
    432                     if( a < 0x90 ) return false;break;
    433 
    434                 case 0xF4:
    435                     if( a > 0x8F ) return false;break;
    436 
    437                 default:
    438                     if( a < 0x80 ) return false;
    439             }
    440 
    441         case 1:
    442             if( *source >= 0x80 && *source < 0xC2 ) return false;
    443     }
    444     if( *source > 0xF4 ) return false;
     297static Boolean isLegalUTF8(const UTF8 *source, int length) {
     298    UTF8 a;
     299    const UTF8 *srcptr = source+length;
     300    switch (length) {
     301    default: return false;
     302        /* Everything else falls through when "true"... */
     303    case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
     304    case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
     305    case 2: if ((a = (*--srcptr)) > 0xBF) return false;
     306
     307        switch (*source) {
     308            /* no fall-through in this inner switch */
     309            case 0xE0: if (a < 0xA0) return false; break;
     310            case 0xED: if ((a < 0x80) || (a > 0x9F)) return false; break;
     311            case 0xF0: if (a < 0x90) return false; break;
     312            case 0xF4: if (a > 0x8F) return false; break;
     313            default:   if (a < 0x80) return false;
     314        }
     315
     316    case 1: if (*source >= 0x80 && *source < 0xC2) return false;
     317    }
     318    if (*source > 0xF4) return false;
    445319    return true;
    446320}
     
    452326 * This is not used here; it's just exported.
    453327 */
     328
     329Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
     330    int length;
     331    if (source == sourceEnd) {
     332        return true;
     333    }
     334    while (true) {
     335        length = trailingBytesForUTF8[*source]+1;
     336        if (source+length > sourceEnd) {
     337            return false;
     338        }
     339        if (!isLegalUTF8(source, length)) {
     340            return false;
     341        }
     342        source += length;
     343        if (source >= sourceEnd) {
     344            return true;
     345        }
     346    }
     347}
     348
     349/**
     350 * This is a variation of isLegalUTF8Sequence() that behaves like g_utf8_validate().
     351 * In addition to knowing if the sequence is legal, it also tells you the last good character.
     352 */
    454353Boolean
    455 isLegalUTF8Sequence( const UTF8 *source,
    456                      const UTF8 *sourceEnd )
     354tr_utf8_validate( const char * str, ssize_t max_len, const char ** end )
    457355{
    458     int length = trailingBytesForUTF8[*source] + 1;
    459 
    460     if( source + length > sourceEnd )
     356    const UTF8* source = (const UTF8*) str;
     357    const UTF8* sourceEnd = source;
     358
     359    if( max_len == 0 )
     360        return true;
     361
     362    if( str == NULL )
     363        return false;
     364
     365    sourceEnd = source + ((max_len < 0) ? strlen(str) : (size_t)max_len);
     366
     367    if( source == sourceEnd )
    461368    {
    462         return false;
    463     }
    464     return isLegalUTF8( source, length );
    465 }
    466 
    467 /* --------------------------------------------------------------------- */
    468 
    469 ConversionResult
    470 ConvertUTF8toUTF16( const UTF8**    sourceStart,
    471                     const UTF8*     sourceEnd,
    472                     UTF16**         targetStart,
    473                     UTF16*          targetEnd,
    474                     ConversionFlags flags )
    475 {
     369        if( end != NULL )
     370            *end = (const char*) source;
     371        return true;
     372    }
     373
     374    for( ;; )
     375    {
     376        const int length = trailingBytesForUTF8[*source] + 1;
     377        if (source + length > sourceEnd) {
     378            if( end != NULL )
     379                *end = (const char*) source;
     380            return false;
     381        }
     382        if (!isLegalUTF8(source, length)) {
     383            if( end != NULL )
     384                *end = (const char*) source;
     385            return false;
     386        }
     387        source += length;
     388        if (source >= sourceEnd) {
     389            if( end != NULL )
     390                *end = (const char*) source;
     391            return true;
     392        }
     393    }
     394
     395   
     396}
     397
     398
     399/* --------------------------------------------------------------------- */
     400
     401ConversionResult ConvertUTF8toUTF16 (
     402        const UTF8** sourceStart, const UTF8* sourceEnd,
     403        UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
    476404    ConversionResult result = conversionOK;
    477     const UTF8*      source = *sourceStart;
    478     UTF16*           target = *targetStart;
    479 
    480     while( source < sourceEnd )
    481     {
    482         UTF32          ch = 0;
    483         unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
    484         if( source + extraBytesToRead >= sourceEnd )
    485         {
    486             result = sourceExhausted; break;
    487         }
    488         /* Do this check whether lenient or strict */
    489         if( !isLegalUTF8( source, extraBytesToRead + 1 ) )
    490         {
    491             result = sourceIllegal;
    492             break;
    493         }
    494         /*
    495          * The cases all fall through. See "Note A" below.
    496          */
    497         switch( extraBytesToRead )
    498         {
    499             case 5:
    500                 ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
    501 
    502             case 4:
    503                 ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
    504 
    505             case 3:
    506                 ch += *source++; ch <<= 6;
    507 
    508             case 2:
    509                 ch += *source++; ch <<= 6;
    510 
    511             case 1:
    512                 ch += *source++; ch <<= 6;
    513 
    514             case 0:
    515                 ch += *source++;
    516         }
    517         ch -= offsetsFromUTF8[extraBytesToRead];
    518 
    519         if( target >= targetEnd )
    520         {
    521             source -= ( extraBytesToRead + 1 ); /* Back up source pointer! */
    522             result = targetExhausted; break;
    523         }
    524         if( ch <= UNI_MAX_BMP ) /* Target is a character <= 0xFFFF */
    525         { /* UTF-16 surrogate values are illegal in UTF-32 */
    526             if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END )
    527             {
    528                 if( flags == strictConversion )
    529                 {
    530                     source -= ( extraBytesToRead + 1 ); /* return to the illegal
    531                                                           value itself */
    532                     result = sourceIllegal;
    533                     break;
    534                 }
    535                 else
    536                 {
    537                     *target++ = UNI_REPLACEMENT_CHAR;
    538                 }
    539             }
    540             else
    541             {
    542                 *target++ = (UTF16)ch; /* normal case */
    543             }
    544         }
    545         else if( ch > UNI_MAX_UTF16 )
    546         {
    547             if( flags == strictConversion )
    548             {
    549                 result = sourceIllegal;
    550                 source -= ( extraBytesToRead + 1 ); /* return to the start */
    551                 break; /* Bail out; shouldn't continue */
    552             }
    553             else
    554             {
    555                 *target++ = UNI_REPLACEMENT_CHAR;
    556             }
    557         }
    558         else
    559         {
    560             /* target is a character in range 0xFFFF - 0x10FFFF. */
    561             if( target + 1 >= targetEnd )
    562             {
    563                 source -= ( extraBytesToRead + 1 ); /* Back up source pointer!
    564                                                       */
    565                 result = targetExhausted; break;
    566             }
    567             ch -= halfBase;
    568             *target++ = (UTF16)( ( ch >> halfShift ) + UNI_SUR_HIGH_START );
    569             *target++ = (UTF16)( ( ch & halfMask ) + UNI_SUR_LOW_START );
    570         }
    571     }
    572 
     405    const UTF8* source = *sourceStart;
     406    UTF16* target = *targetStart;
     407    while (source < sourceEnd) {
     408        UTF32 ch = 0;
     409        unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
     410        if (source + extraBytesToRead >= sourceEnd) {
     411            result = sourceExhausted; break;
     412        }
     413        /* Do this check whether lenient or strict */
     414        if (! isLegalUTF8(source, extraBytesToRead+1)) {
     415            result = sourceIllegal;
     416            break;
     417        }
     418        /*
     419         * The cases all fall through. See "Note A" below.
     420         */
     421        switch (extraBytesToRead) {
     422            case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
     423            case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
     424            case 3: ch += *source++; ch <<= 6;
     425            case 2: ch += *source++; ch <<= 6;
     426            case 1: ch += *source++; ch <<= 6;
     427            case 0: ch += *source++;
     428        }
     429        ch -= offsetsFromUTF8[extraBytesToRead];
     430
     431        if (target >= targetEnd) {
     432            source -= (extraBytesToRead+1); /* Back up source pointer! */
     433            result = targetExhausted; break;
     434        }
     435        if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
     436            /* UTF-16 surrogate values are illegal in UTF-32 */
     437            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
     438                if (flags == strictConversion) {
     439                    source -= (extraBytesToRead+1); /* return to the illegal value itself */
     440                    result = sourceIllegal;
     441                    break;
     442                } else {
     443                    *target++ = UNI_REPLACEMENT_CHAR;
     444                }
     445            } else {
     446                *target++ = (UTF16)ch; /* normal case */
     447            }
     448        } else if (ch > UNI_MAX_UTF16) {
     449            if (flags == strictConversion) {
     450                result = sourceIllegal;
     451                source -= (extraBytesToRead+1); /* return to the start */
     452                break; /* Bail out; shouldn't continue */
     453            } else {
     454                *target++ = UNI_REPLACEMENT_CHAR;
     455            }
     456        } else {
     457            /* target is a character in range 0xFFFF - 0x10FFFF. */
     458            if (target + 1 >= targetEnd) {
     459                source -= (extraBytesToRead+1); /* Back up source pointer! */
     460                result = targetExhausted; break;
     461            }
     462            ch -= halfBase;
     463            *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
     464            *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
     465        }
     466    }
    573467    *sourceStart = source;
    574468    *targetStart = target;
     
    578472/* --------------------------------------------------------------------- */
    579473
    580 ConversionResult
    581 ConvertUTF32toUTF8( const UTF32**   sourceStart,
    582                     const UTF32*    sourceEnd,
    583                     UTF8**          targetStart,
    584                     UTF8*           targetEnd,
    585                     ConversionFlags flags )
    586 {
     474ConversionResult ConvertUTF32toUTF8 (
     475        const UTF32** sourceStart, const UTF32* sourceEnd,
     476        UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
    587477    ConversionResult result = conversionOK;
    588     const UTF32*     source = *sourceStart;
    589     UTF8*            target = *targetStart;
    590 
    591     while( source < sourceEnd )
    592     {
    593         UTF32          ch;
    594         unsigned short bytesToWrite = 0;
    595         const UTF32    byteMask = 0xBF;
    596         const UTF32    byteMark = 0x80;
    597         ch = *source++;
    598         if( flags == strictConversion )
    599         {
    600             /* UTF-16 surrogate values are illegal in UTF-32 */
    601             if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END )
    602             {
    603                 --source; /* return to the illegal value itself */
    604                 result = sourceIllegal;
    605                 break;
    606             }
    607         }
    608         /*
    609          * Figure out how many bytes the result will require. Turn any
    610          * illegally large UTF32 things (> Plane 17) into replacement chars.
    611          */
    612         if( ch < (UTF32)0x80 )
    613         {
    614             bytesToWrite = 1;
    615         }
    616         else if( ch < (UTF32)0x800 )
    617         {
    618             bytesToWrite = 2;
    619         }
    620         else if( ch < (UTF32)0x10000 )
    621         {
    622             bytesToWrite = 3;
    623         }
    624         else if( ch <= UNI_MAX_LEGAL_UTF32 )
    625         {
    626             bytesToWrite = 4;
    627         }
    628         else
    629         {
    630             bytesToWrite = 3;
    631             ch = UNI_REPLACEMENT_CHAR;
    632             result = sourceIllegal;
    633         }
    634 
    635         target += bytesToWrite;
    636         if( target > targetEnd )
    637         {
    638             --source; /* Back up source pointer! */
    639             target -= bytesToWrite; result = targetExhausted; break;
    640         }
    641         switch( bytesToWrite ) /* note: everything falls through. */
    642         {
    643             case 4:
    644                 *--target =
    645                     (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
    646 
    647             case 3:
    648                 *--target =
    649                     (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
    650 
    651             case 2:
    652                 *--target =
    653                     (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
    654 
    655             case 1:
    656                 *--target = (UTF8) ( ch | firstByteMark[bytesToWrite] );
    657         }
    658         target += bytesToWrite;
    659     }
    660 
     478    const UTF32* source = *sourceStart;
     479    UTF8* target = *targetStart;
     480    while (source < sourceEnd) {
     481        UTF32 ch;
     482        unsigned short bytesToWrite = 0;
     483        const UTF32 byteMask = 0xBF;
     484        const UTF32 byteMark = 0x80;
     485        ch = *source++;
     486        if (flags == strictConversion ) {
     487            /* UTF-16 surrogate values are illegal in UTF-32 */
     488            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
     489                --source; /* return to the illegal value itself */
     490                result = sourceIllegal;
     491                break;
     492            }
     493        }
     494        /*
     495         * Figure out how many bytes the result will require. Turn any
     496         * illegally large UTF32 things (> Plane 17) into replacement chars.
     497         */
     498        if (ch < (UTF32)0x80) {      bytesToWrite = 1;
     499        } else if (ch < (UTF32)0x800) {     bytesToWrite = 2;
     500        } else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;
     501        } else if (ch <= UNI_MAX_LEGAL_UTF32) {  bytesToWrite = 4;
     502        } else {                            bytesToWrite = 3;
     503                                            ch = UNI_REPLACEMENT_CHAR;
     504                                            result = sourceIllegal;
     505        }
     506       
     507        target += bytesToWrite;
     508        if (target > targetEnd) {
     509            --source; /* Back up source pointer! */
     510            target -= bytesToWrite; result = targetExhausted; break;
     511        }
     512        switch (bytesToWrite) { /* note: everything falls through. */
     513            case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
     514            case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
     515            case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
     516            case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
     517        }
     518        target += bytesToWrite;
     519    }
    661520    *sourceStart = source;
    662521    *targetStart = target;
     
    666525/* --------------------------------------------------------------------- */
    667526
    668 ConversionResult
    669 ConvertUTF8toUTF32( const UTF8**    sourceStart,
    670                     const UTF8*     sourceEnd,
    671                     UTF32**         targetStart,
    672                     UTF32*          targetEnd,
    673                     ConversionFlags flags )
    674 {
     527ConversionResult ConvertUTF8toUTF32 (
     528        const UTF8** sourceStart, const UTF8* sourceEnd,
     529        UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
    675530    ConversionResult result = conversionOK;
    676     const UTF8*      source = *sourceStart;
    677     UTF32*           target = *targetStart;
    678 
    679     while( source < sourceEnd )
    680     {
    681         UTF32          ch = 0;
    682         unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
    683         if( source + extraBytesToRead >= sourceEnd )
    684         {
    685             result = sourceExhausted; break;
    686         }
    687         /* Do this check whether lenient or strict */
    688         if( !isLegalUTF8( source, extraBytesToRead + 1 ) )
    689         {
    690             result = sourceIllegal;
    691             break;
    692         }
    693         /*
    694          * The cases all fall through. See "Note A" below.
    695          */
    696         switch( extraBytesToRead )
    697         {
    698             case 5:
    699                 ch += *source++; ch <<= 6;
    700 
    701             case 4:
    702                 ch += *source++; ch <<= 6;
    703 
    704             case 3:
    705                 ch += *source++; ch <<= 6;
    706 
    707             case 2:
    708                 ch += *source++; ch <<= 6;
    709 
    710             case 1:
    711                 ch += *source++; ch <<= 6;
    712 
    713             case 0:
    714