version0.7.10
This commit is contained in:
parent
ce88dc3e67
commit
4d4b3b1c04
193 changed files with 9099 additions and 17637 deletions
234
lib/impure/dialogs.nim
Normal file
234
lib/impure/dialogs.nim
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
## This module implements portable dialogs for Nimrod; the implementation
|
||||
## builds on the GTK interface. On Windows, native dialogs are shown if
|
||||
## appropriate.
|
||||
|
||||
import
|
||||
glib2, gtk2
|
||||
|
||||
when defined(Windows):
|
||||
import windows, ShellAPI, os
|
||||
|
||||
type
|
||||
PWindow* = PGtkWindow ## A shortcut for a GTK window.
|
||||
|
||||
proc info*(window: PWindow, msg: string) =
|
||||
## Shows an information message to the user. The process waits until the
|
||||
## user presses the OK button.
|
||||
when defined(Windows):
|
||||
discard MessageBoxA(0, msg, "Information", MB_OK or MB_ICONINFORMATION)
|
||||
else:
|
||||
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
|
||||
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", cstring(msg)))
|
||||
gtk_window_set_title(dialog, "Information")
|
||||
discard gtk_dialog_run(dialog)
|
||||
gtk_widget_destroy(dialog)
|
||||
|
||||
proc warning*(window: PWindow, msg: string) =
|
||||
## Shows a warning message to the user. The process waits until the user
|
||||
## presses the OK button.
|
||||
when defined(Windows):
|
||||
discard MessageBoxA(0, msg, "Warning", MB_OK or MB_ICONWARNING)
|
||||
else:
|
||||
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
|
||||
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", cstring(msg)))
|
||||
gtk_window_set_title(dialog, "Warning")
|
||||
discard gtk_dialog_run(dialog)
|
||||
gtk_widget_destroy(dialog)
|
||||
|
||||
proc error*(window: PWindow, msg: string) =
|
||||
## Shows an error message to the user. The process waits until the user
|
||||
## presses the OK button.
|
||||
when defined(Windows):
|
||||
discard MessageBoxA(0, msg, "Error", MB_OK or MB_ICONERROR)
|
||||
else:
|
||||
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
|
||||
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", cstring(msg)))
|
||||
gtk_window_set_title(dialog, "Error")
|
||||
discard gtk_dialog_run(dialog)
|
||||
gtk_widget_destroy(dialog)
|
||||
|
||||
|
||||
proc ChooseFileToOpen*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a filename from the user. Returns ""
|
||||
## if the user closed the dialog without selecting a file. On Windows,
|
||||
## the native dialog is used, else the GTK dialog is used.
|
||||
when defined(Windows):
|
||||
var
|
||||
opf: TOPENFILENAME
|
||||
buf: array [0..2047, char]
|
||||
opf.lStructSize = sizeof(opf)
|
||||
if root.len > 0:
|
||||
opf.lpstrInitialDir = root
|
||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
||||
opf.flags = OFN_FILEMUSTEXIST
|
||||
opf.lpstrFile = buf
|
||||
opf.nMaxFile = sizeof(buf)
|
||||
var res = GetOpenFileName(addr(opf))
|
||||
if res != 0:
|
||||
result = $buf
|
||||
else:
|
||||
result = ""
|
||||
else:
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Open File", window,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
|
||||
if root.len > 0:
|
||||
discard gtk_file_chooser_set_current_folder(chooser, root)
|
||||
if gtk_dialog_run(chooser) == cint(GTK_RESPONSE_OK):
|
||||
var x = gtk_file_chooser_get_filename(chooser)
|
||||
result = $x
|
||||
g_free(x)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
|
||||
## Opens a dialog that requests filenames from the user. Returns ``@[]``
|
||||
## if the user closed the dialog without selecting a file. On Windows,
|
||||
## the native dialog is used, else the GTK dialog is used.
|
||||
when defined(Windows):
|
||||
var
|
||||
opf: TOPENFILENAME
|
||||
buf: array [0..2047*4, char]
|
||||
opf.lStructSize = sizeof(opf)
|
||||
if root.len > 0:
|
||||
opf.lpstrInitialDir = root
|
||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
||||
opf.flags = OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT or OFN_EXPLORER
|
||||
opf.lpstrFile = buf
|
||||
opf.nMaxFile = sizeof(buf)
|
||||
var res = GetOpenFileName(addr(opf))
|
||||
result = @[]
|
||||
if res != 0:
|
||||
# parsing the result is horrible:
|
||||
var
|
||||
i = 0
|
||||
s: string
|
||||
path = ""
|
||||
while buf[i] != '\0':
|
||||
add(path, buf[i])
|
||||
inc(i)
|
||||
inc(i)
|
||||
if buf[i] != '\0':
|
||||
while true:
|
||||
s = ""
|
||||
while buf[i] != '\0':
|
||||
add(s, buf[i])
|
||||
inc(i)
|
||||
add(result, s)
|
||||
inc(i)
|
||||
if buf[i] == '\0': break
|
||||
for i in 0..result.len-1: result[i] = os.joinPath(path, result[i])
|
||||
else:
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Open Files", window,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
|
||||
if root.len > 0:
|
||||
discard gtk_file_chooser_set_current_folder(chooser, root)
|
||||
gtk_file_chooser_set_select_multiple(chooser, true)
|
||||
result = @[]
|
||||
if gtk_dialog_run(chooser) == cint(GTK_RESPONSE_OK):
|
||||
var L = gtk_file_chooser_get_filenames(chooser)
|
||||
var it = L
|
||||
while it != nil:
|
||||
add(result, $cast[cstring](it.data))
|
||||
g_free(it.data)
|
||||
it = it.next
|
||||
g_slist_free(L)
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
|
||||
proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a filename to save to from the user.
|
||||
## Returns "" if the user closed the dialog without selecting a file.
|
||||
## On Windows, the native dialog is used, else the GTK dialog is used.
|
||||
when defined(Windows):
|
||||
var
|
||||
opf: TOPENFILENAME
|
||||
buf: array [0..2047, char]
|
||||
opf.lStructSize = sizeof(opf)
|
||||
if root.len > 0:
|
||||
opf.lpstrInitialDir = root
|
||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
||||
opf.flags = OFN_OVERWRITEPROMPT
|
||||
opf.lpstrFile = buf
|
||||
opf.nMaxFile = sizeof(buf)
|
||||
var res = GetSaveFileName(addr(opf))
|
||||
if res != 0:
|
||||
result = $buf
|
||||
else:
|
||||
result = ""
|
||||
else:
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Save File", window,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
|
||||
if root.len > 0:
|
||||
discard gtk_file_chooser_set_current_folder(chooser, root)
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(chooser, true)
|
||||
if gtk_dialog_run(chooser) == cint(GTK_RESPONSE_OK):
|
||||
var x = gtk_file_chooser_get_filename(chooser)
|
||||
result = $x
|
||||
g_free(x)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
|
||||
proc ChooseDir*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a directory from the user.
|
||||
## Returns "" if the user closed the dialog without selecting a directory.
|
||||
## On Windows, the native dialog is used, else the GTK dialog is used.
|
||||
when defined(Windows):
|
||||
var
|
||||
lpItemID: PItemIDList
|
||||
BrowseInfo: TBrowseInfo
|
||||
DisplayName: array [0..MAX_PATH, char]
|
||||
TempPath: array [0..MAX_PATH, char]
|
||||
Result = ""
|
||||
#BrowseInfo.hwndOwner = Application.Handle
|
||||
BrowseInfo.pszDisplayName = DisplayName
|
||||
BrowseInfo.ulFlags = 1 #BIF_RETURNONLYFSDIRS
|
||||
lpItemID = SHBrowseForFolder(cast[LPBrowseInfo](addr(BrowseInfo)))
|
||||
if lpItemId != nil:
|
||||
discard SHGetPathFromIDList(lpItemID, TempPath)
|
||||
Result = $TempPath
|
||||
discard GlobalFreePtr(lpItemID)
|
||||
else:
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Select Directory", window,
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
|
||||
if root.len > 0:
|
||||
discard gtk_file_chooser_set_current_folder(chooser, root)
|
||||
if gtk_dialog_run(chooser) == cint(GTK_RESPONSE_OK):
|
||||
var x = gtk_file_chooser_get_filename(chooser)
|
||||
result = $x
|
||||
g_free(x)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
57
lib/impure/web.nim
Normal file
57
lib/impure/web.nim
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module contains simple high-level procedures for dealing with the
|
||||
## web. Use cases:
|
||||
##
|
||||
## * requesting URLs
|
||||
## * sending and retrieving emails
|
||||
## * sending and retrieving files from an FTP server
|
||||
##
|
||||
## Currently only requesting URLs is implemented. The implementation depends
|
||||
## on the libcurl library!
|
||||
|
||||
import libcurl, streams
|
||||
|
||||
proc curlwrapperWrite(p: pointer, size, nmemb: int,
|
||||
data: pointer): int {.cdecl.} =
|
||||
var stream = cast[PStream](data)
|
||||
stream.writeData(stream, p, size*nmemb)
|
||||
return size*nmemb
|
||||
|
||||
proc URLretrieveStream*(url: string): PStream =
|
||||
## retrieves the given `url` and returns a stream which one can read from to
|
||||
## obtain the contents. Returns nil if an error occurs.
|
||||
result = newStringStream()
|
||||
var hCurl = curl_easy_init()
|
||||
if hCurl == nil: return nil
|
||||
if curl_easy_setopt(hCurl, CURLOPT_URL, url) != CURLE_OK: return nil
|
||||
if curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION,
|
||||
curlwrapperWrite) != CURLE_OK: return nil
|
||||
if curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, result) != CURLE_OK: return nil
|
||||
if curl_easy_perform(hCurl) != CURLE_OK: return nil
|
||||
curl_easy_cleanup(hCurl)
|
||||
|
||||
proc URLretrieveString*(url: string): string =
|
||||
## retrieves the given `url` and returns the contents. Returns nil if an
|
||||
## error occurs.
|
||||
var stream = newStringStream()
|
||||
var hCurl = curl_easy_init()
|
||||
if hCurl == nil: return nil
|
||||
if curl_easy_setopt(hCurl, CURLOPT_URL, url) != CURLE_OK: return nil
|
||||
if curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION,
|
||||
curlwrapperWrite) != CURLE_OK: return nil
|
||||
if curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, stream) != CURLE_OK: return nil
|
||||
if curl_easy_perform(hCurl) != CURLE_OK: return nil
|
||||
curl_easy_cleanup(hCurl)
|
||||
result = stream.data
|
||||
|
||||
when isMainModule:
|
||||
echo URLretrieveString("http://nimrod.ethexor.com/")
|
||||
|
||||
144
lib/impure/zipfiles.nim
Normal file
144
lib/impure/zipfiles.nim
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements a zip archive creator/reader/modifier.
|
||||
|
||||
import
|
||||
streams, libzip, times, os
|
||||
|
||||
type
|
||||
TZipArchive* = object of TObject ## represents a zip archive
|
||||
mode: TFileMode
|
||||
w: PZip
|
||||
|
||||
|
||||
proc zipError(z: var TZipArchive) =
|
||||
var e: ref EIO
|
||||
new(e)
|
||||
e.msg = zip_strerror(z.w)
|
||||
raise e
|
||||
|
||||
proc open*(z: var TZipArchive, filename: string, mode: TFileMode = fmRead): bool =
|
||||
## Opens a zip file for reading, writing or appending. All file modes are
|
||||
## supported. Returns true iff successful, false otherwise.
|
||||
var err, flags: int32
|
||||
case mode
|
||||
of fmRead, fmReadWriteExisting, fmAppend: flags = 0
|
||||
of fmWrite:
|
||||
if existsFile(filename): removeFile(filename)
|
||||
flags = ZIP_CREATE or ZIP_EXCL
|
||||
of fmReadWrite: flags = ZIP_CREATE
|
||||
z.w = zip_open(filename, flags, addr(err))
|
||||
z.mode = mode
|
||||
result = z.w != nil
|
||||
|
||||
proc close*(z: var TZipArchive) =
|
||||
## Closes a zip file.
|
||||
zip_close(z.w)
|
||||
|
||||
proc createDir*(z: var TZipArchive, dir: string) =
|
||||
## Creates a directory within the `z` archive. This does not fails if the
|
||||
## directory already exists. Note that for adding a file like
|
||||
## ``"path1/path2/filename"`` it is not necessary
|
||||
## to create the ``"path/path2"`` subdirectories - it will be done
|
||||
## automatically by ``addFile``.
|
||||
assert(z.mode != fmRead)
|
||||
discard zip_add_dir(z.w, dir)
|
||||
zip_error_clear(z.w)
|
||||
|
||||
proc addFile*(z: var TZipArchive, dest, src: string) =
|
||||
## Adds the file `src` to the archive `z` with the name `dest`. `dest`
|
||||
## may contain a path that will be created.
|
||||
assert(z.mode != fmRead)
|
||||
var zipsrc = zip_source_file(z.w, src, 0, -1)
|
||||
if zipsrc == nil:
|
||||
echo("Dest: " & dest)
|
||||
echo("Src: " & src)
|
||||
zipError(z)
|
||||
if zip_add(z.w, dest, zipsrc) < 0'i32:
|
||||
zip_source_free(zipsrc)
|
||||
zipError(z)
|
||||
|
||||
proc addFile*(z: var TZipArchive, file: string) =
|
||||
## A shortcut for ``addFile(z, file, file)``, i.e. the name of the source is
|
||||
## the name of the destination.
|
||||
addFile(z, file, file)
|
||||
|
||||
proc mySourceCallback(state, data: pointer, len: int,
|
||||
cmd: Tzip_source_cmd): int {.cdecl.} =
|
||||
var src = cast[PStream](state)
|
||||
case cmd
|
||||
of ZIP_SOURCE_OPEN:
|
||||
if src.setPosition != nil: src.setPosition(src, 0) # reset
|
||||
of ZIP_SOURCE_READ:
|
||||
result = src.readData(src, data, len)
|
||||
of ZIP_SOURCE_CLOSE: src.close(src)
|
||||
of ZIP_SOURCE_STAT:
|
||||
var stat = cast[PZipStat](data)
|
||||
zip_stat_init(stat)
|
||||
stat.size = high(int32)-1 # we don't know the size
|
||||
stat.mtime = getTime()
|
||||
result = sizeof(TZipStat)
|
||||
of ZIP_SOURCE_ERROR:
|
||||
var err = cast[ptr array[0..1, cint]](data)
|
||||
err[0] = ZIP_ER_INTERNAL
|
||||
err[1] = 0
|
||||
result = 2*sizeof(cint)
|
||||
of constZIP_SOURCE_FREE: GC_unref(src)
|
||||
else: assert(false)
|
||||
|
||||
proc addFile*(z: var TZipArchive, dest: string, src: PStream) =
|
||||
## Adds a file named with `dest` to the archive `z`. `dest`
|
||||
## may contain a path. The file's content is read from the `src` stream.
|
||||
assert(z.mode != fmRead)
|
||||
GC_ref(src)
|
||||
var zipsrc = zip_source_function(z.w, mySourceCallback, cast[pointer](src))
|
||||
if zipsrc == nil: zipError(z)
|
||||
if zip_add(z.w, dest, zipsrc) < 0'i32:
|
||||
zip_source_free(zipsrc)
|
||||
zipError(z)
|
||||
|
||||
# -------------- zip file stream ---------------------------------------------
|
||||
|
||||
type
|
||||
TZipFileStream = object of TStream
|
||||
f: Pzip_file
|
||||
|
||||
PZipFileStream* =
|
||||
ref TZipFileStream ## a reader stream of a file within a zip archive
|
||||
|
||||
proc fsClose(s: PZipFileStream) = zip_fclose(s.f)
|
||||
proc fsReadData(s: PZipFileStream, buffer: pointer, bufLen: int): int =
|
||||
result = zip_fread(s.f, buffer, bufLen)
|
||||
|
||||
proc newZipFileStream(f: PZipFile): PZipFileStream =
|
||||
new(result)
|
||||
result.f = f
|
||||
result.close = fsClose
|
||||
result.readData = fsReadData
|
||||
# other methods are nil!
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
proc getStream*(z: var TZipArchive, filename: string): PZipFileStream =
|
||||
## returns a stream that can be used to read the file named `filename`
|
||||
## from the archive `z`. Returns nil in case of an error.
|
||||
## The returned stream does not support the `setPosition`, `getPosition`,
|
||||
## `writeData` or `atEnd` methods.
|
||||
var x = zip_fopen(z.w, filename, 0'i32)
|
||||
if x != nil: result = newZipFileStream(x)
|
||||
|
||||
iterator walkFiles*(z: var TZipArchive): string =
|
||||
## walks over all files in the archive `z` and returns the filename
|
||||
## (including the path).
|
||||
var i = 0
|
||||
var num = int(zip_get_num_files(z.w))
|
||||
while i < num:
|
||||
yield $zip_get_name(z.w, i, 0'i32)
|
||||
inc(i)
|
||||
Loading…
Add table
Add a link
Reference in a new issue