~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/win32utils.py

  • Committer: Alexander Belchenko
  • Date: 2007-01-30 10:50:14 UTC
  • mto: This revision was merged to the branch mainline in revision 2259.
  • Revision ID: bialix@ukr.net-20070130105014-cc3qlr06htp2zddv
win32utils: Windows-specific functions that use Win32 API via ctypes

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006, 2007 Canonical Ltd
 
2
#
 
3
# Author: Alexander Belchenko
2
4
#
3
5
# This program is free software; you can redistribute it and/or modify
4
6
# it under the terms of the GNU General Public License as published by
14
16
# along with this program; if not, write to the Free Software
15
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
18
 
17
 
 
18
 
"""
19
 
Set of functions to work with console on Windows.
20
 
Author: Alexander Belchenko (e-mail: bialix AT ukr.net)
21
 
License: Public domain
22
 
"""
23
 
 
 
19
"""Win32-specific helper functions
 
20
 
 
21
Only one dependency: ctypes should be installed.
 
22
"""
 
23
 
 
24
import os
24
25
import struct
 
26
import sys
 
27
 
 
28
 
 
29
# Windows version
 
30
if sys.platform == 'win32':
 
31
    _major,_minor,_build,_platform,_text = sys.getwindowsversion()
 
32
    if _platform == 0:
 
33
        raise Exception('This platform does not supported!')
 
34
    elif _platform == 1:
 
35
        winver = 'Windows 98'
 
36
    else:
 
37
        winver = 'Windows NT'
 
38
else:
 
39
    winver = None
 
40
 
25
41
 
26
42
# We can cope without it; use a separate variable to help pyflakes
27
43
try:
28
 
   import ctypes
29
 
   has_ctypes = True
 
44
    import ctypes
 
45
    has_ctypes = True
30
46
except ImportError:
31
47
    has_ctypes = False
32
 
 
33
 
 
 
48
else:
 
49
    if winver == 'Windows 98':
 
50
        create_buffer = ctypes.create_string_buffer
 
51
        suffix = 'A'
 
52
    else:
 
53
        create_buffer = ctypes.create_unicode_buffer
 
54
        suffix = 'W'
 
55
 
 
56
 
 
57
# Special Win32 API constants
 
58
# Handles of std streams
34
59
WIN32_STDIN_HANDLE = -10
35
60
WIN32_STDOUT_HANDLE = -11
36
61
WIN32_STDERR_HANDLE = -12
37
62
 
 
63
# CSIDL constants (from MSDN 2003)
 
64
CSIDL_APPDATA = 0x001A      # Application Data folder
 
65
CSIDL_PERSONAL = 0x0005     # My Documents folder
 
66
 
 
67
# from winapi C headers
 
68
MAX_PATH = 260
 
69
UNLEN = 256
 
70
MAX_COMPUTERNAME_LENGTH = 31
 
71
 
38
72
 
39
73
def get_console_size(defaultx=80, defaulty=25):
40
 
   """ Return size of current console.
41
 
 
42
 
   This function try to determine actual size of current working
43
 
   console window and return tuple (sizex, sizey) if success,
44
 
   or default size (defaultx, defaulty) otherwise.
45
 
 
46
 
   Dependencies: ctypes should be installed.
47
 
   """
48
 
   if not has_ctypes:
49
 
       # no ctypes is found
50
 
       return (defaultx, defaulty)
51
 
 
52
 
   # To avoid problem with redirecting output via pipe
53
 
   # need to use stderr instead of stdout
54
 
   h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
55
 
   csbi = ctypes.create_string_buffer(22)
56
 
   res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
57
 
 
58
 
   if res:
59
 
       (bufx, bufy, curx, cury, wattr,
 
74
    """Return size of current console.
 
75
 
 
76
    This function try to determine actual size of current working
 
77
    console window and return tuple (sizex, sizey) if success,
 
78
    or default size (defaultx, defaulty) otherwise.
 
79
    """
 
80
    if not has_ctypes:
 
81
        # no ctypes is found
 
82
        return (defaultx, defaulty)
 
83
 
 
84
    # To avoid problem with redirecting output via pipe
 
85
    # need to use stderr instead of stdout
 
86
    h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
 
87
    csbi = ctypes.create_string_buffer(22)
 
88
    res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
 
89
 
 
90
    if res:
 
91
        (bufx, bufy, curx, cury, wattr,
60
92
        left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
61
 
       sizex = right - left + 1
62
 
       sizey = bottom - top + 1
63
 
       return (sizex, sizey)
64
 
   else:
65
 
       return (defaultx, defaulty)
 
93
        sizex = right - left + 1
 
94
        sizey = bottom - top + 1
 
95
        return (sizex, sizey)
 
96
    else:
 
97
        return (defaultx, defaulty)
 
98
 
 
99
 
 
100
def get_appdata_location():
 
101
    """Return Application Data location.
 
102
    Return None if we cannot obtain location.
 
103
 
 
104
    Returned value can be unicode or plain sring.
 
105
    To convert plain string to unicode use
 
106
    s.decode(bzrlib.user_encoding)
 
107
    """
 
108
    if has_ctypes:
 
109
        try:
 
110
            SHGetSpecialFolderPath = \
 
111
                ctypes.windll.shell32.SHGetSpecialFolderPathW
 
112
        except AttributeError:
 
113
            pass
 
114
        else:
 
115
            buf = ctypes.create_unicode_buffer(MAX_PATH)
 
116
            if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
 
117
                return buf.value
 
118
    # from env variable
 
119
    appdata = os.environ.get('APPDATA')
 
120
    if appdata:
 
121
        return appdata
 
122
    # if we fall to this point we on win98
 
123
    # at least try C:/WINDOWS/Application Data
 
124
    windir = os.environ.get('windir')
 
125
    if windir:
 
126
        appdata = os.path.join(windir, 'Application Data')
 
127
        if os.path.isdir(appdata):
 
128
            return appdata
 
129
    # did not find anything
 
130
    return None
 
131
 
 
132
 
 
133
def get_home_location():
 
134
    """Return user's home location.
 
135
    Assume on win32 it's the <My Documents> folder.
 
136
    If location cannot be obtained return system drive root,
 
137
    i.e. C:\
 
138
 
 
139
    Returned value can be unicode or plain sring.
 
140
    To convert plain string to unicode use
 
141
    s.decode(bzrlib.user_encoding)
 
142
    """
 
143
    if has_ctypes:
 
144
        try:
 
145
            SHGetSpecialFolderPath = \
 
146
                ctypes.windll.shell32.SHGetSpecialFolderPathW
 
147
        except AttributeError:
 
148
            pass
 
149
        else:
 
150
            buf = ctypes.create_unicode_buffer(MAX_PATH)
 
151
            if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0):
 
152
                return buf.value
 
153
    # try for HOME env variable
 
154
    home = os.path.expanduser('~')
 
155
    if home != '~':
 
156
        return home
 
157
    # at least return windows root directory
 
158
    windir = os.environ.get('windir')
 
159
    if windir:
 
160
        return os.path.splitdrive(windir) + '/'
 
161
    # otherwise C:\ is good enough for 98% users
 
162
    return 'C:/'
 
163
 
 
164
 
 
165
def get_user_name():
 
166
    """Return user name as login name.
 
167
    If name cannot be obtained return None.
 
168
 
 
169
    Returned value can be unicode or plain sring.
 
170
    To convert plain string to unicode use
 
171
    s.decode(bzrlib.user_encoding)
 
172
    """
 
173
    if has_ctypes:
 
174
        try:
 
175
            advapi32 = ctypes.windll.advapi32
 
176
            GetUserName = getattr(advapi32, 'GetUserName'+suffix)
 
177
        except AttributeError:
 
178
            pass
 
179
        else:
 
180
            buf = create_buffer(UNLEN+1)
 
181
            n = ctypes.c_int(UNLEN+1)
 
182
            if GetUserName(buf, ctypes.byref(n)):
 
183
                return buf.value
 
184
    # otherwise try env variables
 
185
    return os.environ.get('USERNAME', None)
 
186
 
 
187
 
 
188
def get_host_name():
 
189
    """Return host machine name.
 
190
    If name cannot be obtained return None.
 
191
 
 
192
    Returned value can be unicode or plain sring.
 
193
    To convert plain string to unicode use
 
194
    s.decode(bzrlib.user_encoding)
 
195
    """
 
196
    if has_ctypes:
 
197
        try:
 
198
            kernel32 = ctypes.windll.kernel32
 
199
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix)
 
200
        except AttributeError:
 
201
            pass
 
202
        else:
 
203
            buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
 
204
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
 
205
            if GetComputerName(buf, ctypes.byref(n)):
 
206
                return buf.value
 
207
    # otherwise try env variables
 
208
    return os.environ.get('COMPUTERNAME', None)
 
209
 
 
210
 
 
211
def _ensure_unicode(s):
 
212
    if s and type(s) != unicode:
 
213
        import bzrlib
 
214
        s = s.decode(bzrlib.user_encoding)
 
215
    return s
 
216
    
 
217
 
 
218
def get_appdata_location_unicode():
 
219
    return _ensure_unicode(get_appdata_location())
 
220
 
 
221
def get_home_location_unicode():
 
222
    return _ensure_unicode(get_home_location())
 
223
 
 
224
def get_user_name_unicode():
 
225
    return _ensure_unicode(get_user_name())
 
226
 
 
227
def get_host_name_unicode():
 
228
    return _ensure_unicode(get_host_name())