REALbasic Cross-Platform Application Development

The System module is always available to your applications. It has a variety of properties and methods that will be of use to you at some time or another, but right now I want to write about two in particular because they are both used to get important information about the native environment your application is running in. They are

System.EnvironmentVariable System.Gestalt

Environment Variables

Windows, Macintosh OS X, and Linux computers all have the concept of environment variables (the current REALbasic document erroneously says that environment variables are available only for OS X and Linux). An environment variable is basically a variable whose value is available to any application running on the computer. They are used for a lot of things, especially with scripting. The reason I mention them here is that they provide another way to get information about the operating system your REALbasic application is running on. In particular, there are some environment variables that contain information similar to that returned by the SpecialFolders() function.

In addition to reading environment values, your application can set them as well. This is most commonly used when writing console applications; later on, when I cover console programming, I will show you an example of how to write a CGI program. CGI programs make heavy use of environment variables. CGI stands for common gateway interface and refers to one method that's used to create dynamic web pages. The web server invokes the script or program and passes information about the request to the CGI program in the form of environment variables. See Chapter 7, "Console Programming and the Shell," for more details.

Environment variables are accessed like this:

Dim s as String s = System.EnvironmentVariable("PATH")

You can set the value of the variables in this manner:

System.EnvironmentVariable("PATH") = "/usr/bin"

These examples get and set the value of the "PATH", which is an environment variable that shows the folders the operating system will look in to find programs that are being executed in the shell. The "PATH" is a list of paths separated by a delimiter, and the operating system searches those paths in the order in which they are listed. I'll talk about the shell more in a later chapter, but this serves as a good example of how to manage cross-platform issues in REALbasic.

In the previous example, I completely overwrote the path when I set it equal to /usr/bin. It is probably a more common task to add another directory to the path, without overwriting the ones that are already listed. To do that, you have to append (or prepend) the new path to the other paths. Windows uses semicolons to separate paths, and Macintosh and Linux both use colons. Therefore, we have three cross-platform issues. The first is that they use different delimiters to separate the list of paths, and the second is that they use different formats for listing paths (backslashes and forward slashes). Finally, all three have different ways of organizing the paths. Let's say our application created a folder called "MyApp" at an appropriate place for that platform and that we have a shell script called "MyScript" in that folder that we want to be able to run. (Don't worry right now about how to make it runsee Chapter 7 for more information.) Here is how you would set the "PATH" variable in your REALbasic application:

[View full width]

#if TargetWin32 then System.EnvironmentVariable("PATH") = System.EnvironmentVariable("PATH") + ";C:\MyApp" #elseif TargetLinux then System.EnvironmentVariable("PATH") = System.EnvironmentVariable("PATH") + ":/usr/local/bin /MyApp" #elseif TargetMachO then System.EnvironmentVariable("PATH") = System.EnvironmentVariable("PATH") + ":/usr/local/bin /MyApp" #endif

One thing I should point out in this example is that you can see that I didn't test for TargetMacOS. Instead, I tested for TargetMachO. That's because the shell does not exist on pre-OS X Macintosh computers, so knowing that it's a Macintosh is not enough information. In this case, I need to know specifically that it is running OS X and I know for sure that if it is Mach-O, it's running OS X. This isn't an entirely satisfactory solution, however, because it is possible that this could be running in a Carbon application, in which case it may be running under OS X or System 9, but I want to run it only under OS X. The trick to determining this is to test to see if you are on a Macintosh platform and then test to see that you are not running on a "Classic" Macintosh. With this in mind, the revised code looks like the following:

[View full width]

#if TargetWin32 then System.EnvironmentVariable("PATH") = System.EnvironmentVariable("PATH") + ";C:\MyApp" #elseif TargetLinux then System.EnvironmentVariable("PATH") = System.EnvironmentVariable("PATH") + ":/usr/local/bin /MyApp" #elseif (TargetMacOS) and NOT(TargetMacOSClassic)then System.EnvironmentVariable("PATH") = System.EnvironmentVariable("PATH") + ":/usr/local/bin /MyApp" #endif

The following tables show some of the basic environment variables you will find on the different platforms.

Table 4.11. Windows XP

Variable

Sample Value

PATH

C:\WINDOWS\System32;C:\apache-ant-1.6.2\bin

APPDATA

C:\Documents and Settings\Mark Choate\Application Data

ALLUSERSPROFILE

C:\Documents and Settings\All Users

COMMONPROGRAMFILES

C:\Program Files\Common Files

COMPUTERNAME

VAIO

COMSPEC

C:\WINDOWS\system32\cmd.exe

HOMEDRIVE

C:

HOMEPATH

\Documents and Settings\Mark Choate

LOGONSERVER

\\VAIO

NUMBER_OF_PROCESSORS

1

OS

Windows_NT

PATHEXT

.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF; .WSH

PROCESSOR_ARCHITECTURE

x86

PROGRAMFILES

C:\Program Files

SESSIONNAME

Console

SYSTEMDRIVE

C:

SYSTEMROOT

C:\WINDOWS

TEMP

C:\DOCUME~1\MARKCH~1\LOCALS~1\Temp

USERDOMAIN

VAIO

USERPROFILE

C:\Documents and Settings\Mark Choate

WINDIR

C:\WINDOWS

Table 4.12. Macintosh

Variable

Sample Value

TERM_PROGRAM

Apple_Terminal

TERM

xterm-color

SHELL

/bin/bash

TERM_PROGRAM_VERSION

133

USER

mchoate

__CF_USER_TEXT_ENCODING

0x1F5:0:0

PATH

/bin:/sbin:/usr/bin:/usr/sbin

PWD

/Users/mchoate

JAVA_HOME

/Library/Java/Home

SHLVL

1

HOME

/Users/mchoate

LOGNAME

mchoate

SECURITYSESSIONID

11a1aef0

_

/usr/bin/env

Table 4.13. Linux

Variable

Sample Value

HOME

/home/mchoate

LESS_ADVANCED_PREPROCESSOR

No

OSTYPE

Linux

LS_OPTIONS

-N --color=tty -T 0

XCURSOR_THEME

Crystalwhite

WINDOWMANAGER

/usr/X11R6/bin/kde

GTK_PATH

/usr/local/lib/gtk-2.0: /opt/gnome/lib/gtk-2.0: /usr/lib/gtk-2.0

G_FILENAME_ENCODING

@locale,UTF-8, ISO-8859-15, CP1252

LESS

-M -I

MACHTYPE

i686-suse-linux

LOGNAME

mchoate

ACLOCAL_FLAGS

-I /opt/gnome/share/aclocal

PKG_CONFIG_PATH

/opt/gnome/lib/pkgconfig

LESSOPEN

lessopen.sh %s

USE_FAM

 

INFOPATH

/usr/local/info: /usr/share/info: /usr/info

DISPLAY

:0.0

LESSCLOSE

lessclose.sh %s %s

G_BROKEN_FILENAMES

1

JAVA_ROOT

/usr/lib/jvm/java

COLORTERM

 

_

/usr/bin/env

System.Gestalt

System.Gestalt is a feature from when REALbasic was a Mac-only application.

System.Gestalt(fourCharCode as String, ByRef result as Integer) as Boolean

In the Macintosh world, you use Gestalt to get a lot of information about the system and environment. This is actually a pre-OS X Carbon thing, but if you are interested in using it, the way it works is that you pass it a four-character code and it returns a numeric value that you will need to interpret. You can find the codes and their possible responses at the following address:

[View full width]

http://developer.apple.com/documentation/Carbon/Reference/Gestalt_Manager/gestalt_ refchap /chapter_1.4_section_1.html

You can use Gestalt to get an incredibly large amount of data about the underlying Macintosh system. The example I give lets you find out exactly which version of the Macintosh system software you are running.

Dim result as Integer If System.Gestalt("sysv", result) = True Then // do something End if

Because result is passed ByRef, it is assigned the value of the answer. The answer is returned as an Integer, but the key to understanding its meaning is to remember that Macintosh uses four-character codes, which are really just another way to say that it is composed of two hexadecimal numbers. One way to get the answer you are looking for is to convert the integer to a hexadecimal number, like this:

Dim s as String s = Hex(result)

Perhaps a better way is to test specifically for the systems you want, like so:

Select Case result Case &h1000 // version 10.0 Case &h1010 // version 10.1 Case &h1020 // version 10.2 Case &h1030 // version 10.3 Case &h1040 // version 10.4 End Select

If your application is going to be saving files in binary format and opening binary files, decide which "endian" you will use as the standard and stick with it. If your application created the binary file and opened the binary file, this is sufficient. At the same time, if you are reading binary data produced by another application on a different platform, you need to be aware of what the endianness is and adjust your work accordingly.

The good news is that while I was writing this book, Apple announced the adoption of Intel chips for future Macintosh computers. This means that the endian problem will be less of a problem in the future.

Line Endings

Each platform uses a different character or string of characters to represent the end of a line of text. REALbasic offers two functions to help you work with different line endings.

EndOfLine Functions

REALbasic.EndOfLine() as String

This function returns the line ending for the current platform.

REALbasic.ReplaceLineEndings(aSourceString as String, aLineEnding as String) as String

This function converts all the line ends in a string to the line ending of your choice. You typically use an EndOfLine property for the aLineEnding parameter, but you could theoretically use whatever you wanted.

EndOfLine Properties

REALbasic.EndOfLine.Windows as String

Windows uses two characters to represent a newline, a carriage return with an ASCII value of "13" followed by a line feed, with an ASCII value of "10" (I bet there are some younger readers who do not know why it is called "carriage return").

REALbasic.EndOfLine.Macintosh as String

Macintosh only uses a carriage return.

REALbasic.EndOfLine.Linux as String

Linux uses a line-feed character only.

The trick to all of this is knowing when these EndOfLine characters are used. If you are typing into an EditField in a REALbasic application, the line ending that is inserted every time you press Enter is going to be a carriage return, regardless of which platform you are on. However, if you open a text file on a Windows machine, there's a good chance it will use the standard carriage return plus line feed (sometimes referred to as CRLF). Likewise, if you write a file on a Windows platform, the line ending will be converted to the local standard.

Although this may seem a little odd at first, it's actually the right way to approach it. If the string was created in REALbasic, you know that the line ending is a carriage return. When you open a file, use the ReplaceLineEndings() function to convert the string that you read from the file so that it uses carriage returns for the string.

Категории