From b8dfbc9c6b54d6976e2d0ae38049c23c618afeed Mon Sep 17 00:00:00 2001 From: Piotr Strzelczyk Date: Tue, 7 Jun 2011 22:42:20 +0000 Subject: configurable tl-tray-menu + example configuration file git-svn-id: svn://tug.org/texlive/trunk@22856 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/texk/texlive/w32_wrapper/tl-tray-menu.c | 403 ++++++++++++--------- Master/tl-tray-menu.exe | Bin 61952 -> 59392 bytes Master/tlpkg/installer/tl-tray-menu-custom.bat | 54 --- Master/tlpkg/installer/tl-tray-menu.ini | 26 ++ Master/tlpkg/tlpsrc/texlive-scripts.tlpsrc | 10 +- 5 files changed, 267 insertions(+), 226 deletions(-) delete mode 100755 Master/tlpkg/installer/tl-tray-menu-custom.bat create mode 100644 Master/tlpkg/installer/tl-tray-menu.ini diff --git a/Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c b/Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c index b848b223898..a9281fd2223 100644 --- a/Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c +++ b/Build/source/texk/texlive/w32_wrapper/tl-tray-menu.c @@ -18,223 +18,290 @@ gcc -Os -s -mwindows -o tl-tray-menu.exe tl-tray-menu-rc.o tl-tray-menu.c #include #include -#define MAX_CMD 32768 +#define MAX_STR 32768 + +static char strBuf[MAX_STR]; -static char msgbuf[4*MAX_PATH]; #define DIE(...) { \ - _snprintf( msgbuf, 4*MAX_PATH, __VA_ARGS__ ); \ - MessageBox( NULL, msgbuf, "ERROR!", MB_ICONERROR | MB_SETFOREGROUND );\ + _snprintf( strBuf, 4*MAX_PATH, __VA_ARGS__ ); \ + MessageBox( NULL, strBuf, "ERROR!", MB_ICONERROR | MB_SETFOREGROUND );\ return 1; \ } #define IDI_ICON 1 // resource number of icon #define IDI_TRAY 100 #define WM_TRAYMSG 101 -#define MENU_TLMGR 0 -#define MENU_TEXDOC 1 -#define MENU_EDITOR 2 -#define MENU_COMSPEC 3 -#define MENU_CUSTOM 4 -#define MENU_EXIT 42 -HMENU hPopMenu; -NOTIFYICONDATA nid; +#define MAX_MENU_ENTRIES 31 +#define MENU_CONFIG ( MAX_MENU_ENTRIES + 1 ) +#define MENU_EXIT ( MAX_MENU_ENTRIES + 2 ) -char szAppName[] = "TrayMenu"; -char ExeList[5][MAX_PATH] = { - "tlmgr-gui.exe", - "texdoctk.exe", - "texworks.exe", - "cmd.exe", - "" -}; +// buffer holding menu labels and commands +// (used only with config file) +static char menuStrings[MAX_STR]; -int CustomHowMessageBox() -{ -} +// default menu labels +char *menuLabels[MAX_MENU_ENTRIES] = { +"&Package Manager", +"&Documentation", +"&Editor", +"&Command Prompt", +NULL }; + +// default menu commands +char *menuCommands[MAX_MENU_ENTRIES] = { +"bin\\win32\\tlmgr-gui.exe", +"bin\\win32\\texdoctk.exe", +"bin\\win32\\texworks.exe", +"tlpkg\\installer\\tl-cmd.bat", +NULL }; + +char configInfo[4*MAX_PATH] = "\ +The menu can be customized with a configuration file.\n\ +For an example and instructions see:\n"; + +HMENU hPopMenu; +NOTIFYICONDATA nid; LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch ( msg ) { - case WM_CREATE: - { - hPopMenu = CreatePopupMenu(); - if ( ExeList[MENU_TLMGR][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_TLMGR, "&Package Manager (tlmgr)" ); - if ( ExeList[MENU_TEXDOC][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_TEXDOC, "&Documentation (texdoc)" ); - if ( ExeList[MENU_EDITOR][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_EDITOR, "&Editor (texworks)" ); - if ( ExeList[MENU_COMSPEC][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_COMSPEC, "&Command Prompt" ); - if ( ExeList[MENU_CUSTOM][0] ) - AppendMenu( hPopMenu, MF_STRING, MENU_CUSTOM, "Custom &Script" ); - else - AppendMenu( hPopMenu, MF_SEPARATOR, 0, NULL ); - AppendMenu( hPopMenu, MF_STRING, MENU_EXIT, "E&xit" ); - } - break; - - case WM_TRAYMSG: - { - switch ( lParam ) + case WM_CREATE: { - case WM_LBUTTONUP: - case WM_RBUTTONUP: + hPopMenu = CreatePopupMenu(); + int i; + for ( i = 0; menuLabels[i]; i++ ) { - POINT pnt; - GetCursorPos( &pnt ); - SetForegroundWindow( hWnd ); // needed to get keyboard focus - TrackPopupMenu( hPopMenu, TPM_LEFTALIGN, pnt.x, pnt.y, TPM_LEFTBUTTON, hWnd, NULL ); + if ( menuCommands[i] ) + AppendMenu( hPopMenu, MF_STRING, i, menuLabels[i] ); } - break; + AppendMenu( hPopMenu, MF_SEPARATOR, 0, NULL ); + AppendMenu( hPopMenu, MF_STRING, MENU_CONFIG, "More..." ); + AppendMenu( hPopMenu, MF_STRING, MENU_EXIT, "E&xit" ); } - } - break; - - case WM_COMMAND: - switch ( LOWORD( wParam ) ) + break; + + case WM_TRAYMSG: { - case MENU_TLMGR: - case MENU_TEXDOC: - case MENU_EDITOR: - case MENU_COMSPEC: - if ( _spawnlp( _P_NOWAIT, ExeList[LOWORD(wParam)], NULL ) < 0 ) - DIE( "Failed to start: %s", ExeList[LOWORD(wParam)] ); - break; - case MENU_CUSTOM: - if ( GetFileAttributes( ExeList[LOWORD(wParam)] ) != INVALID_FILE_ATTRIBUTES ) - { - if ( _spawnlp( _P_NOWAIT, ExeList[LOWORD(wParam)], NULL ) < 0 ) - DIE( "Failed to start: %s", ExeList[LOWORD(wParam)] ); - } - else - MessageBox( - NULL, - "For a custom menu, create tl-tray-menu-custom.bat \nin the root of the installation.\nSee sample at tlpkg\\installer\\tl-tray-menu-custom.bat.", - "Custom menu", - MB_ICONINFORMATION - ); - break; - - case MENU_EXIT: - Shell_NotifyIcon( NIM_DELETE, &nid ); - ExitProcess(0); - break; + switch ( lParam ) + { + case WM_LBUTTONUP: + case WM_RBUTTONUP: + { + POINT pnt; + GetCursorPos( &pnt ); + SetForegroundWindow( hWnd ); // needed to get keyboard focus + TrackPopupMenu( hPopMenu, TPM_LEFTALIGN, pnt.x, pnt.y, 0, hWnd, NULL ); + } + break; + } } - break; + break; + + case WM_COMMAND: + { + switch ( LOWORD( wParam ) ) + { + case MENU_CONFIG: + MessageBox( NULL, configInfo, nid.szTip, MB_SETFOREGROUND ); + break; + + case MENU_EXIT: + Shell_NotifyIcon( NIM_DELETE, &nid ); + ExitProcess(0); + break; + + default: + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + //si.dwFlags = STARTF_USESHOWWINDOW; + //si.wShowWindow = SW_HIDE ; + ZeroMemory( &pi, sizeof(pi) ); + if( !CreateProcess( + NULL, // module name (uses command line if NULL) + menuCommands[LOWORD(wParam)], // command line + NULL, // process security atrributes + NULL, // thread security atrributes + TRUE, // handle inheritance + 0, // creation flags, e.g. CREATE_NO_WINDOW, DETACHED_PROCESS + NULL, // pointer to environment block (uses parent if NULL) + NULL, // starting directory (uses parent if NULL) + &si, // STARTUPINFO structure + &pi ) // PROCESS_INFORMATION structure + ) DIE( "Failed to execute command:\n%s", menuCommands[LOWORD(wParam)] ); + } + } + } + break; + + default: + return DefWindowProc( hWnd, msg, wParam, lParam ); - default: - return DefWindowProc( hWnd, msg, wParam, lParam ); } return 0; } int APIENTRY WinMain( - HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow ) + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow ) { + // scratch variables + + char *s; + // get file name of this executable - static char selfdir[MAX_PATH]; - char *s; - DWORD nchars = GetModuleFileName(NULL, selfdir, MAX_PATH); - if ( !nchars || ( nchars == MAX_PATH ) ) DIE( "cannot get own path" ); - if ( s = strrchr( selfdir, '\\' ) ) *s = '\0'; // remove file name part + static char dirSelf[MAX_PATH]; + DWORD nchars = GetModuleFileName(NULL, dirSelf, MAX_PATH); + if ( !nchars || ( nchars == MAX_PATH ) ) DIE( "Cannot get own path." ); + if ( s = strrchr( dirSelf, '\\' ) ) *s = '\0'; // remove file name part - // append bin/win32 to PATH + // set current directory - static char buffer[MAX_CMD]; - strcpy( buffer, selfdir ); - strcat( buffer, "\\bin\\win32;" ); - strcat( buffer, getenv( "PATH" ) ); - SetEnvironmentVariable( "PATH", buffer ); + if ( !SetCurrentDirectory( dirSelf ) ) + DIE( "Failed to change current directory to:\n%s", dirSelf ); - // set up a list of executables + // prepend bin/win32 to PATH - s = strchr( buffer, ';' ); *s = '\\'; s++; - int i; - for ( i = 0; i < 3; i++ ) - { - *s = '\0'; - strcat( buffer, ExeList[i] ); - if ( GetFileAttributes( buffer ) != INVALID_FILE_ATTRIBUTES ) - strncpy( ExeList[i], buffer, MAX_PATH ); - else - ExeList[i][0] = '\0'; - } + strcpy( strBuf, dirSelf ); + strcat( strBuf, "\\bin\\win32;" ); + strcat( strBuf, getenv( "PATH" ) ); + SetEnvironmentVariable( "PATH", strBuf ); + + // configuration + + static char fileConfig[MAX_PATH]; + s = dirSelf + strlen(dirSelf) + 1; + strcpy( fileConfig, s ); + if ( s = strrchr( fileConfig, '.' ) ) *s = '\0'; // remove file extension part + strcat( fileConfig, ".ini" ); + + strcat( configInfo, dirSelf ); + strcat( configInfo, "\\tlpkg\\installer\\" ); + strcat( configInfo, fileConfig ); - if ( s = getenv( "COMSPEC" ) ) strncpy( ExeList[3], s, MAX_PATH ); + if ( GetFileAttributes( fileConfig ) == INVALID_FILE_ATTRIBUTES ) { - strcpy( buffer, selfdir ); - strcat( buffer, "\\tl-tray-menu-custom.bat" ); - // if ( GetFileAttributes( buffer ) != INVALID_FILE_ATTRIBUTES ) - // At call time, we test for this file and display - // a message box if it is missing. - strncpy( ExeList[4], buffer, MAX_PATH ); + // validate default configuration (menuCommands should be existing files) - // create a hidden window for messaging - - MSG msg; - WNDCLASS wc; - HWND hWnd; - - ZeroMemory( &wc, sizeof wc ); - wc.hInstance = hInstance; - wc.lpszClassName = szAppName; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.style = 0; - wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); - wc.hCursor = LoadCursor( NULL, IDC_ARROW ); - - if ( FALSE == RegisterClass( &wc ) ) DIE( "Failed to register window class" ); - - hWnd = CreateWindow( - szAppName, - "", - 0, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - 0, - 0, - hInstance, - 0); - - if ( hWnd == NULL ) DIE( "Failed to create window" ); - - // tray icon stuff + int i; + for ( i = 0; menuLabels[i]; i++ ) + if ( GetFileAttributes( menuCommands[i] ) == INVALID_FILE_ATTRIBUTES ) + menuCommands[i] = NULL; + + } else { + + // read menu configuration from ini file + + FILE *CONFIG = fopen( fileConfig, "rt" ); + if ( CONFIG == NULL ) + DIE( "Failed to open configuration file:\n%s\\%s", dirSelf, fileConfig ); + + char strSect[] = "[menu]"; + int menuItem = -1; + int i = 0; + int lineNo; + for ( lineNo = 1 ; fgets( strBuf, MAX_STR, CONFIG ) + && menuItem < MAX_MENU_ENTRIES ; lineNo++ ) + { + if ( menuItem < 0 ) + { + if ( *strBuf == '[' && + strncmp( strBuf, strSect, strlen( strSect ) ) == 0 ) menuItem++; + continue; + } + if ( *strBuf == ';' ) continue; // skip comments + if ( *strBuf == '[' ) break; // next section + s = &menuStrings[i]; + i += ExpandEnvironmentStrings( strBuf, s, MAX_STR - i ); + if ( i >= MAX_STR ) + DIE( "Exceeded 32KB limit for configuration." ); + if ( i-2 && menuStrings[i-2] == '\n' ) { menuStrings[i-2] = '\0'; i--; } + menuLabels[menuItem] = s; + while ( *s && *s != '=' ) s++; + if ( *s == '\0' ) + DIE( "Missing '=' on line %d in configuration file:\n%s\\%s", + lineNo, dirSelf, fileConfig ); + *s++ = '\0'; // assign first, then increment + menuCommands[menuItem] = s; + menuItem++; + } + if ( menuItem < 0 ) + DIE( "Missing [menu] section in configuration file:\n%s\\%s", + dirSelf, fileConfig ); + menuLabels[menuItem] = NULL; + menuCommands[menuItem] = NULL; + + fclose( CONFIG ); + + } - nid.cbSize = sizeof nid; - nid.hWnd = hWnd; - nid.uID = IDI_TRAY; - nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; - nid.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_ICON ) ); - nid.uCallbackMessage = WM_TRAYMSG; - strcpy( nid.szTip, "TeX Live Menu" ); + // create a hidden window for messaging + + MSG msg; + WNDCLASS wc; + HWND hWnd; + char szAppName[] = "TrayMenu"; + + ZeroMemory( &wc, sizeof wc ); + wc.hInstance = hInstance; + wc.lpszClassName = szAppName; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.style = 0; + wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + + if ( FALSE == RegisterClass( &wc ) ) DIE( "Failed to register window class" ); + + hWnd = CreateWindow( + szAppName, + "", + 0, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + 0, + 0, + hInstance, + 0); + + if ( hWnd == NULL ) DIE( "Failed to create window" ); + + // tray icon stuff + + nid.cbSize = sizeof nid; + nid.hWnd = hWnd; + nid.uID = IDI_TRAY; + nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; + nid.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_ICON ) ); + nid.uCallbackMessage = WM_TRAYMSG; + strcpy( nid.szTip, "TeX Live Menu" ); #if (_WIN32_IE >= 0X0500) nid.uFlags |= NIF_INFO; nid.dwInfoFlags = NIIF_INFO; strcpy( nid.szInfo, "Click on the tray icon\nto activate the menu." ); strcpy( nid.szInfoTitle, nid.szTip ); #endif - Shell_NotifyIcon( NIM_ADD, &nid ); + Shell_NotifyIcon( NIM_ADD, &nid ); - // main message loop: + // main message loop: - while ( GetMessage( &msg, NULL, 0, 0 ) > 0 ) - { - TranslateMessage( &msg ); - DispatchMessage( &msg ); - } + while ( GetMessage( &msg, NULL, 0, 0 ) > 0 ) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } - return msg.wParam; + return msg.wParam; } diff --git a/Master/tl-tray-menu.exe b/Master/tl-tray-menu.exe index 9593078599c..212430e24dc 100755 Binary files a/Master/tl-tray-menu.exe and b/Master/tl-tray-menu.exe differ diff --git a/Master/tlpkg/installer/tl-tray-menu-custom.bat b/Master/tlpkg/installer/tl-tray-menu-custom.bat deleted file mode 100755 index a44bfdb3e30..00000000000 --- a/Master/tlpkg/installer/tl-tray-menu-custom.bat +++ /dev/null @@ -1,54 +0,0 @@ -@ECHO OFF - -rem Sample custom submenu for the tray menu -rem Usage: edit and copy to the root of the installation. - -rem For a batch-mode main menu, see tlmenu.bat. - -rem Note. The system tray menu has already taken care of the searchpath. - -SETLOCAL ENABLEEXTENSIONS -SETLOCAL ENABLEDELAYEDEXPANSION - -set tlroot=%~dp0 - -:menuloop - -set ans= -cls - -echo === TeX Live Menu === -echo. -echo 1 TexMakerX -echo 2 Emacs -echo 3 Notepad - -echo Q Quit -echo. -set /p ans="Make a choice: " - -if "%ans%"=="1" ( - %tlroot%texmakerx\texmakerx.exe - exit -) - -if "%ans%"=="2" ( - rem load emacs with the included initialization file _emacs - %tlroot%emacs\bin\emacs.exe -q -l %tlroot%emacs\_emacs - exit -) - -if "%ans%"=="3" ( - %windir%\notepad.exe - exit -) - -if "%ans%"=="Q" ( - exit -) - -if "%ans%"=="q" ( - exit -) - -goto :menuloop diff --git a/Master/tlpkg/installer/tl-tray-menu.ini b/Master/tlpkg/installer/tl-tray-menu.ini new file mode 100644 index 00000000000..c93a7b3bdcd --- /dev/null +++ b/Master/tlpkg/installer/tl-tray-menu.ini @@ -0,0 +1,26 @@ +; Example configuration file for TeX Live Menu utility +; (to be placed in the same directory as the menu executable) +; +; * All lines starting with a semicolon are ignored +; * Each line after [menu] must be in the format: +; = +; * No blank lines are allowed nor whitespace around the equal sign +; * Optional '&' in the menu label marks the character for keyboard accelaration +; * Menu commands can contain additional arguments and use environment variables +; (e.g., %WINDIR%). +; * A program to execute in the menu command can be specified by its name only +; (if it is located on the search PATH) or by an absolute or relative file +; path. Relative file paths are resolved relative to the location of the menu +; program (at the root of your TeX Live installation). +; * The directory \bin\win32, where is the directory with +; the menu program, is automatically added to the beginning of the search PATH +; * Number of menu items is limited to 30 and their total size to 32KB +; +[menu] +&Package Manager=tlmgr-gui.exe +&Documentation=texdoctk.exe +&Editor=texworks.exe +;Notepad="%windir%\system32\notepad.exe" +;Your own choice of portable editor: +;&Other editor=texmakerx\texmakerx.exe +&Command Prompt="%COMSPEC%" /k title TeX Live 2011 \ No newline at end of file diff --git a/Master/tlpkg/tlpsrc/texlive-scripts.tlpsrc b/Master/tlpkg/tlpsrc/texlive-scripts.tlpsrc index 9055d4cb1bc..5b47f7afbd6 100644 --- a/Master/tlpkg/tlpsrc/texlive-scripts.tlpsrc +++ b/Master/tlpkg/tlpsrc/texlive-scripts.tlpsrc @@ -13,12 +13,14 @@ runpattern f texmf/scripts/texlive/texconf.tlu binpattern f bin/${ARCH}/rungs binpattern f bin/${ARCH}/man # -# install-tl and tl-portable +# install-tl runpattern f install-tl runpattern f tlpkg/installer/install-menu-*.pl binpattern f/win32 install-tl.bat binpattern f/win32 install-tl-advanced.bat -binpattern f/win32 tl-portable.bat -binpattern f/win32 bin/win32/runscript.* -# docpattern f texmf/doc/man/man1/install-tl.* +# +# runscript and tl-tray-menu +binpattern f/win32 bin/win32/runscript.* +binpattern f/win32 tl-tray-menu.exe +binpattern f/win32 tlpkg/installer/tl-tray-menu.ini -- cgit v1.2.3