dsource Examples (2005-03-22 Snapshot)

Warning: This is a long page. Please be patient waiting for it to load. If page fails to load due to a time-out error, please try again later (when the server may be less busy).

Categories





Examples

Fundamentals

It Compiles

DescriptionIt doesn't actually do anything, but it compiles and runs.
Date/TimeSat May 8, 2004 4:17 pm
Posted byjcc7
void main()
{
}
For an explanation of what this means, visit Wiki4D.

Do Something

DescriptionIt's an abbreviated "hello world" without the world.
Date/TimeWed May 12, 2004 10:01 pm
Posted byjcc7
void main()
{ 
    printf("Hi");
}

Prints "Hi" at the command line.

The printf function is an easy way to send text to the console window. In this example, the quoted phrase is simply printed in the console window.

See more examples on using printf are at Wiki4D.


Initializing Variables

DescriptionShows how to initialize an integer and a string.
Date/TimeMon May 3, 2004 12:12 am
Posted byjcc7
int magicNumber = 42;

char[] password = "sesame";

void main()
{
    printf("Magic number: %d\n", magicNumber);
    printf("Password: %.*s\n", password);
}

Data Types

DescriptionShows how sizeof and max can reveal the size and possible maximum value of data types.
Date/TimeSun May 9, 2004 12:51 am
Posted byjcc7
int main() 
{
    // Show information about integer types...
    printf("bit\tmin: %d\tmax: %d (%u)\n", bit.min, bit.max, bit.sizeof);  
    printf("ubyte\tmin: %u\tmax: %u (%u)\n", ubyte.min, ubyte.max, ubyte.sizeof);  
    printf("ushort\tmin: %u\tmax: %u (%u)\n", ushort.min, ushort.max, ushort.sizeof);  
    printf("uint\tmin: %u\tmax: %u (%u)\n", uint.min, uint.max, uint.sizeof);  
    printf("ulong\tmin: %llu\tmax: %llu (%u)\n", ulong.min, ulong.max, ulong.sizeof);    
    printf("byte\tmin: %d\tmax: %d (%u)\n", byte.min, byte.max, byte.sizeof);  
    printf("short\tmin: %d\tmax: %d (%u)\n", short.min, short.max, short.sizeof);    
    printf("int\tmin: %d\tmax: %d (%u)\n", int.min, int.max, int.sizeof);    
    printf("long\tmin: %lld\tmax: %lld (%u)\n", long.min, long.max, long.sizeof);    

    // Show information about floating-point types...

    printf("float (%u)\tdouble (%u)\treal (%u)\t", float.sizeof, double.sizeof, real.sizeof);
    printf("ifloat (%u)\tidouble (%u)\tireal (%u)\t", ifloat.sizeof, idouble.sizeof, ireal.sizeof);
    printf("cfloat (%u)\tcdouble (%u)\tcreal (%u)\t", cfloat.sizeof, cdouble.sizeof, creal.sizeof);
    printf("cfloat (%u)\tcdouble (%u)\tcreal (%u)\t", cfloat.sizeof, cdouble.sizeof, creal.sizeof);

    // Show information about character types...

    printf("char (%u)\twchar (%u)\tdchar (%u)\t", char.sizeof, wchar.sizeof, dchar.sizeof);


    /* 

    *** sizeof vs. size ***

    Currently the sizeof and size attributes act the same way (and carry the same role). 
    Since this is extremely redundant, it's safe to assume that only one of these will 
    remain in D. Walter has indicated that he prefers sizeof since it's already a keyword 
    in C that is used in a similar fashion. I'd recommended using sizeof rather than size.

    */

    return 0;


}

I'm trying to start with the basics: whole numbers. The above code will show the upper and lower limits for the integer data types in D and sizes for other data types. It's pretty fancy, so hopefully I'm doing this right. I make use of the min and max attributes.

Output

bit min: 0 max: 1 (1)
ubyte min: 0 max: 255 (1)
ushort min: 0 max: 65535 (2)
uint min: 0 max: 4294967295 (4)
ulong min: 0 max: 18446744073709551615 (8)
byte min: -128 max: 127 (1)
short min: -32768 max: 32767 (2)
int min: -2147483648 max: 2147483647 (4)
long min: -9223372036854775808 max: 9223372036854775807 (8)
float (4) double (8) real (10) ifloat (4) idouble (8)
ireal (10) cfloat (8) cdouble (16) creal (20) cfloat (8)
cdouble (16) creal (20) char (1) wchar (2) dchar (4)

Integer Types

TypeMinMaxSize (bytes)
bit 0 11
ubyte 0 2551
ushort 0 65,5352
uint 0 4,294,967,2954
ulong 0 18,446,744,073,709,551,6158
byte -128 1271
short -32,768 32,7672
int -2,147,483,648 2,147,483,6474
long -9,223,372,036,854,775,808 9,223,372,036,854,775,8078

Floating-Point Types

  • Floating point:
    • float
    • double
    • real
  • Complex and Imaginary:
    • cfloat
    • cdouble
    • creal
  • Complex and Imaginary:
    • ifloat
    • idouble
    • ireal

Character Types

  • char: unsigned 8 bit (UTF-8)
  • wchar: unsigned 16 bit (UTF-16)
  • dchar: unsigned 32 bit (UTF-32)

The official list is in the D Specification, of course.


If/Else

DescriptionSimple (yet effective) flow control.
Date/TimeMon May 3, 2004 12:11 am
Posted byjcc7
void main()
{
    int i;
    if(i==0) printf("It's one!"); else printf("It's not one!");
}

The "for" Loop

DescriptionHow to do the same thing over and over again.
Date/TimeMon May 3, 2004 12:10 am
Posted byjcc7
int main()

{   
   for (int i=1; i<=10; i++)
   {
      printf("%d\n", i);
   }
   return 0;


}

Variables

DescriptionCreating "slots" to store data.
Date/TimeSun May 9, 2004 8:18 pm
Posted byjcc7
void main()
{
    int myInt;
    int myint;
    int MYINT;
}

Declare three separate integer variable called myInt, myint, and MYINT.

Like many things in D, variable declarations are a lot like C, C++, and Java.

In D, all variables have to be declared before they are used..

Some Facts About Identifiers
  1. Identifiers must begin with a letter.
  2. Subsequent characters can be numbers or underscores as well as additional letters.
  3. Identifiers can be as long as you want.
  4. Note that variable identifiers in D are case-sensitive. (In the above example, "myInt", "myint", and "MYINT" are separate identifiers.)

Expressions

DescriptionDemonstrates using mathematical expressions.
Date/TimeMon May 3, 2004 12:10 am
Posted byjcc7
import std.c.stdio; /* for using printf */


void main()
{
    int i, j;


    i = 12 * 12; /* multiplication */

    printf("12 x 12 = %d\n", i); /* i should be 144 */

    j = i / 8; /* division */
    printf("144 / 8 = %d\n", j); /* j should be 18 */

    i -= 44; /* same as saying "i = i - 44;" */
    printf("144 - 44 = %d\n", i); /* i should be 100 */

}

Comments

DescriptionGood documentation is a good idea.
Date/TimeSun May 9, 2004 12:27 am
Posted byjcc7

There are three types of comments in D:

  1. Line comments: //
  2. Block comments: /* */
  3. Nested comments: /+ +/

Line Comments

Line comments begin with // and continue until the end of the line. The comment automatically ends at the end of the line, so make sure the next line is valid code. If you want a multiple-line comment, then use a block comment or a nested comment. (If your code gets word-wrapped, your code would break, but you probably should try avoiding editors that word-wrap your code anyways.)

If you're familiar with modern flavors of BASIC, // is equivalent to a '.

Block Comments

Block comments can exist entirely a line or contain multiple lines of commentary. Block comments begin with a /* and end with a */. If you forget a matching closing symbol, your code will either do something you didn't expect, or it won't compile at all. Block comments don't nest. If you want nesting comments, then use nested comments.

Nested Comments

Nested comments can exist entirely a line or contain multiple lines of commentary. Nested comments begin with a /+ and end with a +/. Just like block comments, openning comment markers must be matched with closing marks.

These comments do nest so that you can put one inside another. The most obvious use for this feature is to "comment out" code that you don't want to compile right now (because you're not sure if it's any good) but might be valuable code. Of course, once you decide it's garbage, you'd want to delete the whole passage. Nested comments are a little more complicated than single-line or block comments, so they aren't used in the in this fairly simple example included below.

/* 
comments.html 
Author: J C Calvarese
License: public domain

This program demonstrates using comments in D.
(Such as the multi-line comment this sentence resides in.)
*/

import std.c.stdio; // This is the module that allows us to use printf later...

/*   
    This is another block (or multiline) comment.  
*/

int main()  
{ 
     /* The main function is where the action starts in D. */

    
    printf("This program is documented.\n"); // This command prints some text...
    
    // "printf"" is actually a C command. 
        
    // This is a single line comment.  It automatically ends at the end of the line.

    return /* 0 is an int */ 0;


    
    /* 
        since main is supposed to return an int ("integer"), 
        the above command is required... 
    */ 
}

String Comparison Operators

DescriptionShows how strings are compared.
Date/TimeMon May 3, 2004 12:11 am
Posted byjcc7
/*

Title:      String Operations
File:       string_ops.d
Author:     J C Calvarese, http://jcc_7.tripod.com/d/
Date:       2003/10/07
License:    Public Domain

*/


int main()
{
    char[] str1 = "Aardvark";
    char[] str2 = "Zebra";
    char[] str3 = "1";
    
    
    /* "less than" operator */

    
    if ( str1 < str2 ) 
      printf("Aardvark comes before Zebra.\n");
    else
      printf("Aardvark comes after Zebra.\n");
    
    
    /* "greater" than operator */
    
    if ( str1 > str2 ) 
      printf("Aardvark comes after Zebra.\n");
    else

      printf("Aardvark comes before Zebra.\n");
    
    
    /* "equality" operator */
    
    if ( str1 == str2 ) 
      printf("Aardvark is Zebra?!\n");
    else
      printf("Aardvark is NOT Zebra.\n");
    
    
    /* "concatenation" operator */

    
    for (int i=0; i<3; i++) 
      str3 ~= "0";
    printf("%.*s\n", str3);
    
    return 0;



}

Wait

DescriptionDemonstrates several ways to wait for the user to press a key. (Designed for Windows).
Date/TimeMon May 3, 2004 12:08 am
Posted byjcc7
import std.c.stdio; /* for getch() */
import std.stream; /* for stdin */

extern (C) int system (char *);

void main()
{ 
    printf("Press a key (using 'std.c.stdio.getch();' to wait) . . .\n\0");
    getch();
    
    printf("Press another key (using 'std.stream.stdin.getch();') . . .\n\0");
    std.stream.stdin.getch();
    
    printf("Waiting again\n(using 'system(\"pause\");'):\n\0");
    system("pause");
}

Function

DescriptionUsing a function, you can code it once and then call it when you need it, wherever you need it.
Date/TimeMon May 3, 2004 12:08 am
Posted byjcc7
uint squareIt(uint x)
{
    return x * x;
}


void main()
{
    int i;
    printf("%d\t(initial value)\n", i);


    i = squareIt(3);
    printf("%d\t(3 * 3)\n", i);

    i = squareIt(4);
    printf("%d\t(4 * 4)\n", i);

    i = squareIt(5);
    printf("%d\t(5 * 5)\n", i);
}

Nested Functions

DescriptionNested functions allows you to structure functions in a clever way if that's how your mind works.
Date/TimeMon May 3, 2004 12:09 am
Posted byjcc7
/*

    File:       nested.d
    Author:     J C Calvarese, http://jcc_7.tripod.com/d/
    License:    Public Domain
    Purpose:    To show how nested functions work in D.

See also the D Specification.

*/




int main(char[][] Args)
{
    int i;

    void runIt()
    {
        /* 
            This is a nested function.
            You can make use of variables
            declared in the outer function,
            but each has to be declared above
            the location of the nested function
            if you use it.
        */

    
        printf("%d\tdo something\t", i);

    }


    bit found;

    while (!found)
    {

        if(i==0)


        {
            printf("not found\t");
            runIt();
            return 0;



        }
        found = true;

    }

    return 0;


}

Struct

DescriptionStructs allow you to bind together basic data types into a more complicated paradigm.
Date/TimeMon May 3, 2004 12:09 am
Posted byjcc7
import std.c.stdio;



struct Vehicle
{  
    double cost;
    int wheels;
}


struct Utensil
{ 
    bit pointy;
    bit tined;  
}




void main()
{  
    
    Vehicle car;
    car.cost = 20_000;
    car.wheels = 4;
    
    Vehicle motorcycle;
    motorcycle.cost = 2_000;
    motorcycle.wheels = 2;
    
    Vehicle boat;
    boat.cost = 5_000; 
    boat.wheels = 0;


    Utensil spoon;
    spoon.pointy = false;
    spoon.tined = false;
    
    Utensil fork;
    fork.pointy = true;
    fork.tined = true;
    
    Utensil knife;
    knife.pointy = true;
    knife.tined = false;
}

Struct Initialization

DescriptionShows a quick way to initialize a struct.
Date/TimeMon May 3, 2004 12:16 am
Posted byjcc7
/*
From: Vathix
Subject: Re: new struct initializer syntax
Date: Fri, 30 Jan 2004 06:42:53 -0500
Xref: digitalmars.com D:22815
http://www.digitalmars.com/drn-bin/wwwnews?D/22815
*/

struct Foo
{
    int bar, baz, bam;
}

void main()
{

static Foo[] myfoo =  [
    { 0, 1, 2 },
    { bar: 3, baz: 4, bam: 5 },
    { bam: 8, baz: 7, bar: 6 },
];

}

Class

DescriptionA class is a similiar idea to a struct, but allows more abstract designs.
Date/TimeMon May 3, 2004 12:09 am
Posted byjcc7
import std.c.stdio;


class Television
{ 
    
    void pressPowerButton()
    {
        if(m_turnedOn)
            printf("It was on, but now you turned it off.\n");  
        else
            printf("Now, it's turned on (channel %d).\n", m_channel);
        m_turnedOn = !m_turnedOn;
    }
    
    void changeChannel(int c)
    {  
        if(m_turnedOn)
        {
            if(c == m_channel)
                printf("It's already on channel %d, silly.\n", m_channel);
            else

            { 
                printf("Per your request, it's now on channel %d.\n", m_channel);
                m_channel = c;
            }
        }
        else
            printf("Hmm... the TV's off. Try turning it on before you pick a channel.\n", m_channel);
                
    }
    
    this()
    {
        m_turnedOn = false;  
        m_channel = 3;
        printf("\n(Creating this object is kind of like plugging in a TV set.)\n\n");
    }
    
    ~this()
    { 
        printf("\n(Destroying this object is kind of like unplugging a TV set.)\n\n");
    }
    
    private

    {  
        bit m_turnedOn;
        int m_channel;
    }
}


void main()
{ 
    
    Television BigScreen = new Television();
    
    BigScreen.pressPowerButton();
    BigScreen.changeChannel(44);
    BigScreen.changeChannel(49);
    BigScreen.changeChannel(49);
    BigScreen.pressPowerButton();
    BigScreen.changeChannel(34);
    BigScreen.pressPowerButton();
    BigScreen.changeChannel(34);
    BigScreen.changeChannel(49);
    BigScreen.pressPowerButton();
    
    delete BigScreen;
}

Appending

DescriptionShows how appending works with D dynamic strings.
Date/TimeFri May 14, 2004 10:14 pm
Posted byjcc7
void main()
{
    char[] s;
    printf("Length: %d\tString: '%.*s'\n", s.length, s);

    s ~= "something ";
    printf("Length: %d\tString: '%.*s'\n", s.length, s);

    s ~= "whatever";
    printf("Length: %d\tString: '%.*s'\n", s.length, s);
}

Assertions

DescriptionIf you can determine it's wrong at compile-time, why bother running it?
Date/TimeMon May 3, 2004 12:06 am
Posted byjcc7
/*
 
    File:       assert.d
    Author:     Justin C. Calvarese, http://jcc_7.tripod.com/d/
    License:    Public Domain
    Purpose:    Demonstrates what an assertion does in D.

     See also the D Specification (http://www.digitalmars.com/d/expression.html#assertexpression).

*/
 


void main()
{  

    printf("Let's test some assertions...\n");

    /* These assertions should succeed --
       they evaluate to true. */

    assert(true);
    assert('\xAA' == '\u00AA');
    assert(221 % 5 == 1);
    assert(25 * 4 * 20 + 4 == 2004);
    
    /*  
        This assertion fails... 
        Error: AssertError Failure assert.d(line number) 
    */

    
    assert(false);
    
    printf("\nNo problem, man.\n");
}

Unittests

DescriptionUnittests let you find the bugs before you even run the program.
Date/TimeMon May 3, 2004 12:06 am
Posted byjcc7
module unittests;


void main()
{
    printf("test\n");
    /* This assertion will fail. */
    assert(false);  

    /* 
        The line number (7) may be different, but this is the 
        error message which should appear...
        Error: AssertError Failure unittests(7)
    */

}


class Whatever
{
   
    unittest

    
    {
        /*  unittests seem to be run in the order they appear in the code, i.e. since 
            the Whatever class appears before the module unittests, these are run first. 

            The -unittests flag has to be used to compile this program or else this code is ignored.
        

            This sample batch file compiles the code (including unittests) and then runs the executable.

            @echo off
            dmd unittests.d -unittest && unittests.exe
            pause
        */

        printf("class Whatever UnitTest...\n");
        /* If the expession of an assert doesn't evaluate to true, an exception is thrown at run-time. */

        assert(true==1);
        assert(true);
        assert(false==false);
        assert(!false);
    }
}



unittest
{
    printf("module UnitTest...\n");
    assert(true==1);
    assert(true);
    assert(false==false);
}

Getch/Getchar

DescriptionGet a character from the keyboard.
Date/TimeSat Oct 30, 2004 3:25 pm
Posted byjcc7
import std.c.stdio;
import std.string;



void main()
{ 
    char k;

    printf("\nI'm going to ask you to press 10 keys (I promise it's painless).\n"
    "Certain keys don't count, but the whole alphabet is fair game.\n\n");

    for(int i=0; i<10; i++)
    {
        version(Windows)
        {
            printf("Press key: %d\t", i);
            k = getch();
        }
        version(Linux)
        {
            printf("Press key (follow with return): %d\t", i);
            k = getchar();
        }
        printf("[%c]\t", k);            /* print the character pressed */

        printf("[%d]\n", cast(int) k);  /* print ASCII code for key */
    }
    printf("\nThe End.\n\n");
}

2004-06-01: Added an untested Linux version based on a suggestion.


Intermediate

Using more than one function

DescriptionThis D program shows you how to use more than one function in D.
Date/TimeMon Mar 14, 2005 11:06 pm
Posted byjcc7
/*
    Multiple functions in D
    By B-man
    If you have any comments or questions e-mail me at
    bman_099@yahoo.com
*/

import std.c.stdio;      //Use the standard C library stdio

int main()       //main function
{
    char input_text[26];     //Create an array that will hold the input 
    printf ("Now using the main() function\n");
    printf ("type somthing and press ENTER ");  
    scanf ("%*.s",input_text[25]);   //Scanf function. allows user input.

    function2();  //call the 'function2()' function
    return 0;  //don't return an error
}

function2()  //function2() function
{
    printf ("now using the function2() function\n");
    return 0; //don't return an error

}

/* Originally submitted by bman_099@yahoo.com (Sat Feb 5, 2005 3:15 pm). */ 

Character Initial Values

DescriptionTests the initial values for character types.
Date/TimeSun Jun 27, 2004 5:19 pm
Posted byjcc7
void main()
{
    if(char.init == 0)


        printf("DMD 0.92 char.init.\n");
    if(wchar.init == 0)

        printf("DMD 0.92 wchar.init.\n");
    if(dchar.init == 0)


        printf("DMD 0.92 dchar.init.\n");

    if(char.init == 0xFF)
        printf("DMD 0.93+ char.init.\n");
    if(wchar.init == 0xFFFF)
        printf("DMD 0.93+ wchar.init.\n");
    if(wchar.init == 0x0000FFFF)
        printf("DMD 0.93+ dchar.init.\n");
}

Module usage

DescriptionSimple decoder and encoder with 8bit and 16bit lookups in separate module with initialization. Also demonstrates associative arrays, foreach. and bit array.
Date/TimeSat Oct 2, 2004 9:14 am
Posted byAnonymous
// There are two separate source code files to be split.
// Test.d -- compile with dmd test.d Lookup.d

/*
 * Encoding:
 * Each word in a text is checked whether it is found in a 256 entry
 * dictionary08 (8 bits) or 512 entry dictionary16 (16 bits). A bit array
 * called "eightCode" is used to indicate which dictionary contained
 * the word. Associative arrays are used for the dictionaries.
 * "codes08" is an array of bytes with the sequence of 'hits' from
 * dictionary08. "codes16" is an array of ushorts with the sequence of
 * 'hits' from dictionary16.
 *
 * Decoding:
 * The "eightCode" bit array is traversed. If true, the corresponding word
 * is pulled from lookup08. If false, the corresponding word is pulled from
 * lookup16. The original "text" is compared with "check" for validation.
 *
 * Caveats:
 * - written by relatively inexperienced D programmer
 * - accomplishes so-so compression with fast decompression
 * 
 * Visual Studio 98 ide project files, exe, and full source available from:
 * http://bibledb.sourceforge.net/misc/ModuleTutorial.zip
 */

import Lookup;

import std.stdio;
import std.string;


const char[][] check  = ["", "", "", "", "", "", "", "", "", ""];

const char[][] text   = ["In", "the", "beginning", "God", "created", 
                         "the", "heavens", "and", "the", "earth."];


ubyte[10]  codes08;
ushort[10] codes16;
bit[10]    eightCode;

void main()
{
  Encode();

  Decode();
}

void Encode()
{
  int  i8 = 0;


  int  i16 = 0;

  foreach (int i, char[] word; text) {
    debug char* w = word;
    if (word in dictionary08) {
      uint code08 = dictionary08[word];
      writef("8:", code08, ' ');
      codes08[i8] = code08;
      i8++;
      eightCode[i] = true;
      continue;
    }
    if (word in dictionary16) {
      uint code16 = dictionary16[word];
      writef("16:", code16, ' ');
      codes16[i16] = code16;
      i16++;
      eightCode[i] = false;
      continue;
    }
    writefln("\nUnmatched word: ", word);
  }
  writefln();
}


void Decode()
{
  int i8 = 0;

  int i16 = 0;


  foreach(int i, bit b; eightCode) {
    char[] curWord;
    if (b == true) {
      curWord = lookup08[codes08[i8]];
      check[i] = curWord;
      writefln(curWord, ' ');
      i8++;
    }
    else {
      curWord = lookup16[codes16[i16]];
      check[i] = curWord;
      writefln(curWord, ' ');
      i16++;
    }
  }
  writefln();
  assert(check == text);
}




// Lookup.d
module Lookup;

static this() {
  foreach (int index, char[] word; lookup08) {
    dictionary08[word] = index;
  }
  foreach (int index, char[] word; lookup16) {
    dictionary16[word] = index;
  }
  dictionary08.rehash;
  dictionary16.rehash;
}

int[char[]] dictionary08;
int[char[]] dictionary16;

char[][] lookup08 = [
"the","and","of","to","in","that","And","he",

"a","I","his","for","shall","is","be","you",
"they","with","will","not","all","your","have","was",

"my","it","from","their","on","are","which","unto",
"them","him","as","were","who","by","said","out",

"but","had","when","this","God","The","up","came",
"into","man","him,","one","there","thy","thou","me",

"said,","come","made","before","no","king","For","has",
"against","son","But","children","put","at","LORD","went",

"we","them,","you,","an","her","ye","Lord","go",
"give","may","make","Then","do","let","people","house",

"He","land","or","so","saying,","men","our","me,",
"even","because","if","upon","Israel","also","every","day",

"after","take","over","these","beginning","great","took","among",
"down","am","did","those","hath","sons","like","she",

"O","gave","us","things","what","So","hand","him.",
"away","Israel,","two","any","sent","then","Jehovah","Now",

"Jesus","whom","Yahweh","given","They","David","brought","them.",
"been","name","say","shalt","word","according","thee","it,",

"you.","know","saw","forth","nor","see","neither","should",
"good","You","evil","its","LORD,","set","through","days",

"Lord,","me.","place","about","now","bring","therefore","If",
"Let","hundred","more","than","would","people,","behold,","heart",

"thee,","Moses","holy","father","way","keep","saith","God.",
"time","done","without","words","own","heard","called","it.",

"When","three","might","where","Behold,","seven","taken","other",
"In","under","It","man,","yet","say,","hast","thousand",

"right","earth","first","This","offering","eat","Judah","house,",
"many","how","again","off","city","himself","whose","cast",

"eyes","back","Israel.","servant","full","Thus","years","voice",
"Yahweh,","Jehovah,","cut","hands","fear","work","turned","cause",

"servants","high","Therefore","says","What","young","until","priest"
];


char[][] lookup16 = [
"created","day,","commanded","send","land,","same","pass","face",

"Judah,","end","glory","thing","together","up,","My","five",
"found","round","death","them;","us,","living","men,","answered",

"speak","As","blood","A","thine","seen","four","toward",
"being","fire","law","son,","hand,","old","very","priests",

"year","side","life","king,","earth,","themselves","sin","Jerusalem,",
"rest","love","soul","Who","cities","another","Jerusalem","Moses,",

"her,","Saul","dwell","There","woman","some","All","both",
"Christ","LORD.","Thou","get","gone","fathers","much","kept",

"chief","Egypt,","hear","become","These","stood","kingdom","him;",
"daughter","between","pass,","became","Son","none","part","only",

"strong","king's","knowledge","having","nations","such","left","burnt",
"ten","flesh","able","them:","mouth","head","tell","near",

"told","certain","That","twenty","little","you;","spake","him:",
"concerning","Why","spoke","midst","till","power","Because","laid",

"We","city,","spirit","turn","David,","you:","faith","bread",
"Aaron","delivered","and,","thus","tribe","altar","mine","while",

"gathered","thereof","deliver","heaven","number","thee.","Solomon","Lord.",
"seed","earth.","mighty","me:","far","drink","thereof,","long",

"me;","water","day.","people.","heart,","peace","Jacob","comes",
"wise","waters","praise","can","Go","things,","pray","father,",

"out,","food","destroy","whole","fell","not,","lay","come,",
"brother","sword","offer","art","seek","lifted","wrath","well",

"heaven,","ark","To","How","six","angel","wife","wicked",
"nothing","spoken","though","mercy","gold","does","covenant","broken",

"fathers,","place,","it;","away,","land.","light","house.","why",
"burned","dead","Of","stand","unclean","Egypt","silver","Take",

"fruit","third","new","don't","save","Spirit","ever.","surely",
"God;","down,","Is","Give","now,","sight","Joshua","gold,",

"inhabitants","offerings","Jerusalem.","written","ear","got","brothers,","bear",
"family","serve","righteousness","second","return","Jews","Israel:","way,",

"princes","walk","didn't","Holy","places","sons,","works","offering,",
"answer","Yahweh.","sea","disciples","judge","going","fall","this,",

"God:","prophet","desire","war","sat","smote","lest","Levites",
"known","us.","lord","Israel;","book","Be","daughters","began",

"Your","body","His","strength","gives","built","righteous","door",
"coming","Jehovah.","Philistines","still","together,","Christ,","open","hold",

"ever","multitude","begat","Father","you?","days,","call","above",
"within","gate","Joseph","thirty","hand.","reigned","waste","men.",

"cry","priest,","forty","Jesus,","yourselves","twelve","false","eyes,",
"sea,","feet","passed","it:","child","there,","servant,","death.",

"receive","find","servants,","wisdom","name,","time,","ready","poor",
"place.","field","death,","night","Pharaoh","tabernacle","sword,","again,",

"mother","mount","brothers","month,","prophets","border","One","sacrifice",
"show","could","not.","never","joy","knew","clear","Abraham",

"whether","witness","build","blessed","cried","I,","makes","throughout",
"vessels","children,","carried","wine","Do","wife,","enter","returned",

"law,","cubits","middle","goes","life,","By","stone","destruction",
"grace","manner","fifty","ears","received","fire,","worship","dead,",

"Ye","women","help","anger","orders","nations,","me?","seventh",
"inheritance","filled","also,","elders","voice,","captain","LORD:","gather",

"asked","father's","saying","prayer","that,","world","town","kill",
"ways","offered","cannot","oil","valley","slew","most","hope",

"congregation","here","better","priests,",
"himself,","commandment","sought","silver,",
"Peter","LORD;","brethren,","Babylon,","true","must","sheep","gods",

"Jeremiah","looking","half","rose","man's","east","covered","Jacob,",
"meat","fat","burn","another,","male","side,","country","captains",

"look","there.","away.","named","departed","Babylon","shut","break",
"numbered","meet","king.","judgment","Have","brother,","water,","money",

"times","Samuel","King","burning","morning","heads","feast","army",
"thee;","seeing","lie","her.","families","month","Paul","therefore,",

"iniquity","houses","Even","Moreover","Egypt.","She","Aaron,","wilderness",
"wall","in,","fine","answered,","flesh,","words,","die","making",

"born","sins","night,","wherein","live","appointed","sound","heavens"
];

Asm code for splitting ubyte into low and high nibbles

DescriptionDemonstrates using asm code with local variables
Date/TimeMon Oct 4, 2004 10:47 am
Posted byAnonymous
/*
 *  Copyright (C) 2004 by Digital Mars, www.digitalmars.com
 *  Written by Lynn Allan
 *  This software is provided 'as-is' by a rusty asm-486 programmer.
 *  Released to public domain.
 *
 * Compile with: dmd test.d (uses dmd ver 0.102)
 */

import std.stdio;

void main ()
{
  ubyte x = 0x12;
  ubyte y = 0x9a;
  ubyte xLoNibble = (x & 0x0F);
  ubyte xHiNibble = (x >> 4);
  ubyte yLoNibble = (y & 0x0F);
  ubyte yHiNibble = (y >> 4);
  writefln("x: ", x, "  xLoNibble: ", xLoNibble, "  xHiNibble: ", xHiNibble);
  writefln("y: ", y, "  yLoNibble: ", yLoNibble, "  yHiNibble: ", yHiNibble);

  asm

  {
    movzx  BX,x;
    mov    AX,BX;
    and    BX,15;
    mov    xLoNibble,BL;
    shr    AX,4;
    mov    xHiNibble,AL;

    movzx  BX,y;
    mov    AX,BX;
    and    BX,15;
    mov    yLoNibble,BL;
    shr    AX,4;
    mov    yHiNibble,AL;
  }
  assert(xLoNibble == 2);
  assert(xHiNibble == 1);
  assert(yLoNibble == 10);
  assert(yHiNibble == 9);
  writefln("x: ", x, "  xLoNibble: ", xLoNibble, "  xHiNibble: ", xHiNibble);
  writefln("y: ", y, "  yLoNibble: ", yLoNibble, "  yHiNibble: ", yHiNibble);
}

Asm code for finding first occurrence of letter in string

DescriptionMore or less equivalent to std.string.find. (also similar to C-RTL for strchr except finds count offset rather than char*). Demonstrates reference of local char[] variable, repne, scasb, etc.
Date/TimeMon Oct 4, 2004 10:57 am
Posted byAnonymous
/*
 *  Copyright (C) 2004 by Digital Mars, www.digitalmars.com
 *  Written by Lynn Allan
 *  This software is provided 'as-is' by a rusty asm-486 programmer.
 *  Released to public domain.
 *
 * Compile with: dmd test.d (uses dmd ver 0.102)
 */

import std.stdio;
import std.string;

void main ()
{
  char[] searchString = "The quick brown fox jumped over the lazy dog.";
  //                     00000000001111111111222222222233333333334444

  //                     01234567890123456789012345678901234567890123
  char* pss = &searchString[0];
  uint foundOffset = find(searchString, 'z');
  uint zCode = 'z';
  uint len = searchString.length;
  writefln("z found at: ", foundOffset);
  uint xCode = 'x';
  foundOffset = find(searchString, 'x');
  len = searchString.length;
  writefln("x found at: ", foundOffset);

  asm {
    cld;
    mov   ECX,len;
    mov   EAX,zCode;
    mov   EDI,pss;
    repne;
    scasb;
    mov   EBX,len;
    sub   EBX,ECX;
    dec   EBX;
    mov   foundOffset,EBX;
  }
  writefln("z found at: ", foundOffset);
  assert(foundOffset==38);

  asm {
    cld;
    mov   ECX,len;
    mov   EAX,xCode;
    mov   EDI,pss;
    repne;
    scasb;
    mov   EBX,len;
    sub   EBX,ECX;
    dec   EBX;
    mov   foundOffset,EBX;
  }
  writefln("x found at: ", foundOffset);
  assert(foundOffset==18);
}

Towers of Hanoi

DescriptionSolves the Hanoi problem for seven discs.
Date/TimeFri Dec 3, 2004 10:44 pm
Posted byAnonymous
/+
 + hanoi!
 + solves the hanoi problem for seven discs
 +
 + by Brian Waters
 +/

import std.c.stdio;

int main(char[][] args)
{
    void solve(int from, int aux, int to, int numdiscs)
    {
        if (numdiscs == 0)


            return;
        solve(from, to, aux, numdiscs - 1);
        printf("%i to %i\n", from, to);
        solve(aux, from, to, numdiscs - 1);
        return;
    }
    
    solve(1, 2, 3, 7);
    
    return 0;


}

Factorial

DescriptionShows how a factorial function can be written using a for loop.
Date/TimeMon May 3, 2004 12:18 am
Posted byjcc7
uint factorial(int a)
{

    /*
        A factorial is a mathematical concept that is typically denoted with a "!".

        Example:
        4! = 4 * 3 * 2 * 1 = 24
    */


    if(a == 0) return 1;

    uint b = 1;
    for(int i = 1; i <= a; i++)
        b *= i;
    return b;
}


import std.c.stdio;

unittest
{

    /* Compile with the "-unittest" option to run these unittests. */

    printf("Attempting unittests...\n");
    assert(factorial(0) == 1);
    assert(factorial(1) == 1);
    assert(factorial(2) == 2);
    assert(factorial(3) == 6);
    assert(factorial(4) == 24);
    printf("unittests successful...\n");
}


void main()
{
    printf("factorial(0): %d\n", factorial(0));
    printf("factorial(1): %d\n", factorial(1));
    printf("factorial(2): %d\n", factorial(2));
    printf("factorial(3): %d\n", factorial(3));
    printf("factorial(4): %d\n", factorial(4));
}

Escape Sequences

DescriptionEscape sequence are useful, but they can get tricky.
Date/TimeMon May 3, 2004 12:19 am
Posted byjcc7
/*

File:    escape.d
Author:  J C Calvarese
Website: http://jcc_7.tripod.com/d/
License: Public Domain

Purpose: 
Demonstrates how to use escaping to put backslashes and apostrophes 
for a literal character.

*/

const char[] backslashWYSIWYG = `\`;
const char[] quoteWYSIWYG = `'`;
const char[] doubleQuoteWYSIWYG = `"`;


const char[] doubleQuoteReg = "\"";
const char[] quoteReg = "\'";
const char[] backslahReg = "\\";



const char quoteChar = '\'';

const char backslashChar = '\\';



void main()
{
    printf(cast(char[]) (doubleQuoteReg ~ "That's what I said!" ~ doubleQuoteReg ~ \n\0));  
}

Comments (Reprise)

DescriptionMore comments is better than fewer comments.
Date/TimeFri May 14, 2004 10:45 pm
Posted byjcc7
module comments;

/* This purpose of this code is to 
   show how documentation can be done with comments. */


/*/   */


// single line


import std.string;


/*

Mult-line

*/

int usefulInteger;

/+ 

simple nested

+/

char[] someString;

/+ 
/+/ +/
level 1 nested

    /+
    
    level 2 nested
    
        /+
        level 3 nested
        +/
    
    +/

+/


/* The actual program (anti-climatic) */

int main()
{
    char[] someOtherString = someString;
    
    int anotherInt = usefulInteger;
    
    return 0;


}

Nested Comments

DescriptionThis program doesn't do anything, but it's well-documented.
Date/TimeMon May 3, 2004 12:18 am
Posted byjcc7
/* 

nested_comments.html 

Author: J C Calvarese
License: public domain

This program demonstrates using comments in D.

(Such as the multi-line comment this sentence resides in.)

*/



/+   

    This is one of D's nested comments.  


    /+ What would an example of a nested comment be without 
       a nested (and /+ another nest +/ )comment? +/

    /* Naturally, you can also put something like this in a nested multiline comments... */

    // as well as text like like this ...

    /* since the compiler is only concerned about being in a nested comment block,
        you don't actually need a matching * and / to satisfy the compiler.

+/



void main()  
{ // This is a single line comment.  It automatically ends at the end of the line.
}

String Literals

DescriptionShows how different types of string literals work.
Date/TimeSat Jun 19, 2004 4:30 pm
Posted byjcc7
/* "Backquote" WYSIWYG strings */

const char[] a1 = `\`;
const char[] b1 = `\\`;
const char[] c1 = `\"`;




/* r"" WYSIWYG strings */

const char[] a2 = r"\";
const char[] b2 = r"\\";
const char[] c2 = r"\" `"`; 
/* The r"" strings can't contain a ", so I used concatenation. */



/* "Regular strings */

const char[] a3 = "\\";
const char[] b3 = "\\\\";

const char[] c3 = "\\\"";



void main()
{
    printf("Test that the strings mean what I think they mean.\n");

    assert(a1 == a2);
    assert(a1 == a3);

    assert(b1 == b2);
    assert(b1 == b3);

    assert(c1 == c2);
    assert(c1 == c3);

    printf("Tests passed!\n");

}

String and Number Literals

DescriptionWhen DMD 0.69 was released, I came up with this example to try it out.
Date/TimeSat Jun 19, 2004 4:23 pm
Posted byjcc7
/* 

File:      d069.d
Author:    Justin C. Calvarese
Website:   http://jcc_7.tripod.com/d/
License:   Public Domain

Purpose:
Since D 0.69, integer and floating point literals
can have embedded underscores (_) for formatting purposes.

This code demonstrates those features and more...

*/

const int hundred = 100;
const int million = 1_000_000;




/*

Also added in 0.69...

x"0a AA BF" style hex strings.

*/

const char[] myName = x"4A 75 73 74 69 6E"; 


const char[] notRaw = "string\tstring";


/*

Raw (what-you-see-is-what-you-get) strings
implemented in D 0.69

*/

const char[] raw1 = r"string\tstring";
const char[] raw2 = `string\tstring`;
const char[] raw3 = `apostrophe: '  fancy quote: ` ~ "`";




/* See how the strings are automatically concatenated... */
const char[] oneToFive = "one" \t "two" \t "three" \t "four" \t  \t "five";


/* Binary Notation: I'm saying "two" */
const int binTwo      = 0b10;
const int binFancyTwo = 0b000_0010;

/* Hexadecimal Notation: I'm saying "16" */

const int hexSixteen      = 0x10;
const int hexFancySixteen = 0x00_10;

/* Hexadecimal Notation: I'm saying "8" */
const int octEight = 010;


int main() 
{

    /* Print "1000000" */
    printf("%i\n", million);    

    /* Print "2" */
    printf("%i\n", binTwo);  

    /* Print "16" */

    printf("%i\n", hexSixteen);  

    /* Print "8" */
    printf("%i\n", octEight);  


    /* Print "Justin" */
    printf("%.*s\n", myName);   

    /* Print a string with backslashed characters */

    printf("\"Invisible\" backslashed characters: %.*s\n", notRaw); 

    /* Prints a what-you-see-is-what-you-get string */
    printf("What-you-see-is-what-you-get [1]: %.*s\n", raw1);   

    /* Prints a what-you-see-is-what-you-get string */
    printf("What-you-see-is-what-you-get [2]: %.*s\n", raw2);   

    /* Prints a what-you-see-is-what-you-get string */

    printf("What-you-see-is-what-you-get [3]: %.*s\n", raw3);   

    /* Prints one to five */
    printf("one-to-five: %.*s\n\n", oneToFive);


    printf("This is the first line.
This is the second line.
I'd say that D is pretty darn cool (third line).

");


    return 0;


}

Runtime Type Information (RTTI)

DescriptionYou can find out some class information during runtime.
Date/TimeMon May 3, 2004 12:18 am
Posted byjcc7
import std.c.stdio;

class A {}

int main ( char [] [] args ) 
{
    A a = new A;
    Object o;
    o = new Object;
    bit b;
    
    printf("%.*s\n", a.classinfo.name);
    printf("%.*s\n", o.classinfo.name);

    /* These aren't allowed... */

//    printf("%.*s\n", b.classinfo.name);
//    printf("%.*s\n", b.typeinfo.name);

    return 1;
}

/* 

See also: 
http://www.prowiki.org/wiki4d/wiki.cgi?HowTo/RealtimeTypeInformation
http://www.prowiki.org/wiki4d/wiki.cgi?FaqRoadmap#DoesDsupportanyformofRTTI

*/ 

Statistics

DescriptionDemonstrates calculating linear regression statistics.
Date/TimeMon May 3, 2004 12:22 am
Posted byjcc7
/*

File:      stat.d
Author:    Justin C. Calvarese
Website:   http://jcc_7.tripod.com/d/
License:   Public Domain

Linear regression statistics.

*/



double average(double[] r)
{
    double t = 0;



    for(int i=0; i < r.length; i++)
     t += r[i];

    return (t / (cast(double) r.length));
}



double beta1(double[] x, double[] y, double x_bar, double y_bar)
{
    int l;

    if (x.length != y.length) 
    {
        printf("x and y really should be the same length!");

        // Set length as the shorter series and move on...

        if(x.length < y.length) l = x.length;
        else l = y.length;
    }
    else l = x.length;


    double top_sum, btm_sum;

    top_sum = 0;


    for(int i = 0; i < l; i++)
     top_sum += (x[i] - x_bar) * (y[i] - y_bar);


    btm_sum = 0;


    for(int i = 0; i < l; i++)
     btm_sum += ((x[i] - x_bar) * (x[i] - x_bar));


    return top_sum / btm_sum;
}





double beta0(double x_bar, double y_bar, double b1)
{
    return y_bar - (b1 * x_bar);
}





int main()
{

    double[] x;

    x.length = 10;

    x[0] = 1;
    x[1] = 2;
    x[2] = 3;
    x[3] = 4;
    x[4] = 5;
    x[5] = 6.5;
    x[6] = 7;
    x[7] = 7.5;
    x[8] = 8;
    x[9] = 8.5 ;


    double[] y;

    y.length = 10;

    y[0] = 1;
    y[1] = 2;
    y[2] = 3;
    y[3] = 3.2;
    y[4] = 3.4;
    y[5] = 4;
    y[6] = 4.2;
    y[7] = 4.3;
    y[8] = 4.35;
    y[9] = 4.37;


    double x_bar, y_bar;

    x_bar = average(x);
    y_bar = average(y);


    double b1, b0;
    b1 = beta1(x, y, x_bar, y_bar);    
    b0 = beta0(x_bar, y_bar, b1);    

    printf("b1: %f\n", b1);
    printf("b0: %f\n", b0);


    return 0;



}

Advanced

Date Localization using version

DescriptionLocalization example that shows how to use version to compile different versions to use different date formats.
Date/TimeThu May 20, 2004 11:20 pm
Posted byjcc7
/*

locales2.d

Author:  Justin C Calvarese
Date:    October 7, 2003
License: Public Domain

Demonstrates using version() to handle different locales.

Compile for the United States locale:
dmd locales.d -version=UNITED_STATES

Compile for the Canadian (English) locale:
dmd locales.d -version=CANADIAN_ENGLISH

These date formats are based on 
"docs.sun.com: International Language Environments Guide"
http://docs.sun.com/db/doc/806-6642/6jfipqu57?a=view

*/


import std.string;


char[] dateString(byte day, byte month, int yr)
{ 
    int twoDigitYr = yr % 100;
    
    version(CANADIAN_ENGLISH) return leadingZeros(day, 2) ~ "/" ~ leadingZeros(month, 2) ~ "/" ~ leadingZeros(twoDigitYr, 2);
    version(DANISH)           return toString(yr) ~ "-" ~ leadingZeros(month, 2) ~ "-" ~ leadingZeros(day, 2);
    version(FINNISH)          return leadingZeros(day, 2) ~ "." ~ leadingZeros(month, 2) ~ "." ~ toString(yr);
    version(FRENCH)           return leadingZeros(day, 2) ~ "/" ~ leadingZeros(month, 2) ~ "/" ~ toString(yr);
    version(GERMAN)           return toString(yr) ~ "-" ~ leadingZeros(month, 2) ~ "-" ~ leadingZeros(day, 2);
    version(ITALIAN)          return leadingZeros(day, 2) ~ "/" ~ leadingZeros(month, 2) ~ "/" ~ leadingZeros(twoDigitYr, 2);
    version(NORWEGIAN)        return leadingZeros(day, 2) ~ "-" ~ leadingZeros(month, 2) ~ "-" ~ leadingZeros(twoDigitYr, 2);
    version(SPANISH)          return leadingZeros(day, 2) ~ "-" ~ leadingZeros(month, 2) ~ "-" ~ leadingZeros(twoDigitYr, 2);
    version(SWEDISH)          return toString(yr) ~ "-" ~ leadingZeros(month, 2) ~ "-" ~ leadingZeros(day, 2);
    version(GREAT_BRITAIN)    return leadingZeros(day, 2) ~ "/" ~ leadingZeros(month, 2) ~ "/" ~ leadingZeros(twoDigitYr, 2);
    version(UNITED_STATES)    return leadingZeros(month, 2) ~ "-" ~ leadingZeros(day, 2) ~ "-" ~ leadingZeros(twoDigitYr, 2);   
    version(THAI)             return leadingZeros(day, 2) ~ "/" ~ leadingZeros(month, 2) ~ "/" ~ toString(yr);      
}



char[] leadingZeros(byte num, byte digits)
/* also in currency.d and with.d */
{ 
    char[] buffer;
    byte diff;
    
    buffer = toString(num);
    if (buffer.length < digits) 
    {
        diff = digits - buffer.length;
        for(int i=0; i < diff; i++)
          buffer = "0" ~ buffer;
    } 
    return buffer;
}



int main()
{ 
    printf("%.*s\n", dateString(24, 8, 2001));
    return 0;


}

Struct "constructors"

DescriptionDefine a constructor-like function for structs
Date/TimeThu May 20, 2004 11:21 pm
Posted byjcc7
struct Foo {
  int a;
  static Foo opCall(int a) {
    Foo s;
    s.a = a;
    return s;
  }
}
int main() {
  Foo x = Foo(10);
  printf("%d\n", x.a);
  return 0;


}

Application path

DescriptionShows how to find the path of the current executable (Windows-only).
Date/TimeThu Sep 23, 2004 9:44 am
Posted byjcc7
import std.c.windows.windows;
import std.c.stdio;
import std.string;



extern(C) int strlen(char* c);

extern(Windows) 
{
    DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);   
    HMODULE GetModuleHandleA(LPCSTR lpModuleName);
}

    
char[] AppExePath()
{
    /* returns the Path to the current .exe module (e.g. "F:\PGM\D\TRAYICON\") */
    
    char[] strtmp;
    strtmp.length = 1024;

    GetModuleFileNameA(GetModuleHandleA(null), cast(char*) strtmp, 1024);
    int j = rfind(strtmp[0..strlen(strtmp)], "\\");

    strtmp = strtmp[0..j+1];
    return strtmp;
}



void main()
{  
    printf("%.*s\n", AppExePath);
    
}

Locales

DescriptionAn example using version that shows how to use version to compile different executables for different languages.
Date/TimeThu May 20, 2004 11:20 pm
Posted byjcc7
/*

locales1.d

Author:  Justin C Calvarese
Date:    October 6, 2003
License: Public Domain

Demonstrates using version() to handle different locales.

Compile for the English locale:
dmd locales.d -version=English

Compile for the German locale:
dmd locales.d -version=Deutsch

*/

version(English)  
{
    const char[] salutation = "Hi";
    const char[] negative = "No";
}


version(Espanol) 
{
    const char[] salutation = "Hola";
    const char[] negative = "No";
} 

version(Francais)
{
    const char[] salutation = "Bonjour";
    const char[] negative = "Non";
} 


version(Deutsch)  
{
    const char[] salutation = "Hallo";
    const char[] negative = "Nein";
} 


int main()
{ 
    printf("%.*s\n", salutation);
    return 0;



}

CreateLink using COM

DescriptionShows using COM to create a shortcut (Windows).
Date/TimeMon May 3, 2004 12:14 am
Posted byjcc7
/* 

IShellLink Example for D

File:      createLink.d
Author:    Justin C Calvarese
Website:   http://jcc_7.tripod.com/d/
License:   Public Domain


- Ported to DMD D version 0.59 from BCX/LCC-Win32 by J C Calvarese
- Based on "BCX COM EXAMPLE" (by dl_programmer) 
- BCX source in makelink.zip at http://groups.yahoo.com/group/BCX/files/Source_Code/
- Creates a Windows shortcut to an executable, adding several properties.


Compile like this...
dmd createLink ole32.lib uuid.lib


Link with:   

ole32.lib    
---------
_CoUninitialize@0
_CoInitialize@4
_CoCreateInstance@20

uuid.lib
--------
_CLSID_ShellLink


If you want an .ico file you can use mine:
http://jcc_7.tripod.com/d/tutor/fldr_a.ico

*/

import std.c.windows.windows;
import std.string;

import std.c.windows.com;



/* Windows API constants */

const int SW_SHOW =5;
const int CP_ACP = 0;  //  default to ANSI code page


extern(C) const GUID CLSID_ShellLink     = {0x00021401, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]};

extern(C) const IID IID_IShellLinkA      = {0x000214EE, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]};

extern(C) const IID IID_IPersistFile     = {0x0000010B, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]};

alias IID_IShellLinkA IID_IShellLink;



/* Windows API types */

alias ushort *LPWSTR;

struct SHITEMID {
    USHORT cb;
    BYTE abID[1];
} 
alias SHITEMID* LPSHITEMID;


struct ITEMIDLIST {
    SHITEMID mkid;
}
alias ITEMIDLIST* LPCITEMIDLIST;
alias ITEMIDLIST* LPITEMIDLIST;


struct WIN32_FIND_DATA 
{
    DWORD dwFileAttributes;
    FILETIME ftCreationTime;
    FILETIME ftLastAccessTime;
    FILETIME ftLastWriteTime;
    DWORD nFileSizeHigh;
    DWORD nFileSizeLow;
    DWORD dwReserved0;
    DWORD dwReserved1;
    char cFileName[MAX_PATH];
    char cAlternateFileName[14];
    WORD dummy;
} 

alias WIN32_FIND_DATA* LPWIN32_FIND_DATA, PWIN32_FIND_DATA;

struct WIN32_FIND_DATAA 
{
    DWORD dwFileAttributes;
    FILETIME ftCreationTime;
    FILETIME ftLastAccessTime;
    FILETIME ftLastWriteTime;
    DWORD nFileSizeHigh;
    DWORD nFileSizeLow;
    DWORD dwReserved0;
    DWORD dwReserved1;
    CHAR cFileName[MAX_PATH];
    CHAR cAlternateFileName[14];
    WORD dummy;
}
alias WIN32_FIND_DATAA* LPWIN32_FIND_DATAA, PWIN32_FIND_DATAA;

struct WIN32_FIND_DATAW 
{
        DWORD dwFileAttributes;
        FILETIME ftCreationTime;
        FILETIME ftLastAccessTime;
        FILETIME ftLastWriteTime;
        DWORD nFileSizeHigh;
        DWORD nFileSizeLow;
        DWORD dwReserved0;
        DWORD dwReserved1;
        WCHAR cFileName[MAX_PATH];
        WCHAR cAlternateFileName[14];
        WORD dummy;
}
alias WIN32_FIND_DATAW* LPWIN32_FIND_DATAW, PWIN32_FIND_DATAW;




/* Windows API functions */


extern(Windows) int MultiByteToWideChar(UINT, DWORD, LPCSTR, int, LPWSTR, int);

alias MessageBoxA MessageBox;



/* objidl.h excerpt */

extern(C) /+const+/ extern IID /+IID_IPersistFile+/ IID_IPERSISTFILE;

extern(Windows) interface IPersistFile: IUnknown
{
/+    HRESULT (_stdcall *QueryInterface)(IPersistFile*,REFIID,void **);
    ULONG (_stdcall *AddRef)(IPersistFile*);
    ULONG (_stdcall *Release)(IPersistFile*);+/

    HRESULT GetClassID(CLSID*);
    HRESULT IsDirty();
    HRESULT Load(LPCOLESTR, DWORD);
    HRESULT Save(LPCOLESTR, BOOL);
    HRESULT SaveCompleted(LPCOLESTR);
    HRESULT GetCurFile(LPOLESTR*);
}

/* end of objidl.h excerpt */



/* shobjidl.h excerpt */

extern(Windows) interface IPersistIDList: IUnknown
{
/+   HRESULT QueryInterface(REFIID, void **);
   ULONG AddRef();
   ULONG Release();+/

   HRESULT GetClassID(CLSID*);
   HRESULT SetIDList(LPCITEMIDLIST);
   HRESULT GetIDList(LPITEMIDLIST*);
}

extern(Windows) interface IShellLink: IUnknown
{
/+   HRESULT QueryInterface(REFIID, void **);
   ULONG AddRef();
   ULONG Release();+/
   HRESULT GetPath(LPSTR, int, WIN32_FIND_DATAA*, DWORD);
   HRESULT GetIDList(LPITEMIDLIST*);
   HRESULT SetIDList(LPCITEMIDLIST);
   HRESULT GetDescription(LPSTR, int);
   HRESULT SetDescription(LPCSTR);
   HRESULT GetWorkingDirectory(LPSTR, int);
   HRESULT SetWorkingDirectory(LPCSTR);
   HRESULT GetArguments(LPSTR, int);
   HRESULT SetArguments(LPCSTR);
   HRESULT GetHotkey(WORD*);
   HRESULT SetHotkey(WORD);
   HRESULT GetShowCmd(int*);
   HRESULT SetShowCmd(int);
   HRESULT GetIconLocation(LPSTR, int, int*);
   HRESULT SetIconLocation(LPCSTR, int);
   HRESULT SetRelativePath(LPCSTR, DWORD);
   HRESULT Resolve(HWND, DWORD);
   HRESULT SetPath(LPCSTR);
}


/* end of shobjidl.h excerpt */



void main()
{

    /* You'll probably need to change some paths to reflect your system. */
    
    char[] SCPath = "c:\\windows\\";
    char[] szFile;
    char[] szTarget;
    char[] szDesc;
    char[] szIcon;
 

    szFile   = SCPath ~ "explorer.exe";
    szTarget = SCPath ~ "d_shortcut.lnk";

    szIcon = "c:\\dmd\\src\\jcc_7\\examples\\various\\fldr_a.ico";
    szDesc = "Shortcut to test.lnk using D!";

    if (CreateLink(szFile, szTarget, szDesc, szIcon) == S_OK)
        MessageBox(null, "Your shortcut has been created!",  "Look at that, D does do COM!", 0);

    else
        MessageBox(null, "An error occured while trying to create your shortcut", "Aw man...", 0); 
}



/* Helpful functions */

char[] Left(char[] s, int leng)
{
    /* Left$(s$, leng) */
    if (leng <= s.length) return s[0..leng];
    return s[];
} 



char[] AppPath(char[] path)
{
  /* --------------------------------------------------------------------------
     DESCRIPTION: Gets a path from full path name
           INPUT: String to full path name
          OUTPUT: String to path name
           USAGE: buffer$ = AppPath$("c:\your directory\your file.exe")
         RETURNS: c:\your directory\
     -------------------------------------------------------------------------- */
    return Left(path, find(path, cast(char[]) "\\"));
}


HRESULT CreateLink(char[] lpszPathObj, char[] lpszPathLink,  char[] lpszDesc, char[] lpszIcon)
{
   /* --------------------------------------------------------------------------
      DESCRIPTION: Creates a Windows shortcut
            INPUT: string to EXE, string to shortcut, string to description,
                   string to icon
           OUTPUT: HRESULT to success or failure
            USAGE: result = CreateLink("c:\in.exe", "c:\out.lnk, "description")
          RETURNS: S_OK if the interface is supported, E_NOINTERFACE if not.
      -------------------------------------------------------------------------- */

    
    HRESULT hres;
    IShellLink psl;

    CoInitialize(null);     /* Initialize the COM object */

    /* Get a pointer to the IShellLink interface. */
    hres = CoCreateInstance(&CLSID_ShellLink, null, CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl);

    if (SUCCEEDED(hres)) 
    {
        IPersistFile ppf;

        /* Sets shortcut location */

        psl.SetPath(cast(char*) (lpszPathObj ~ \0));

        /* Sets shortcut description */
        psl.SetDescription(cast(char*) (lpszDesc ~ \0));

        /* Gives shortcut an icon */

        psl.SetIconLocation(cast(char*) (lpszIcon ~ \0), 0);

        /* Make it full screen */
        psl.SetShowCmd(SW_SHOW); /* MAXIMIZED */

        /* Set default path */
        psl.SetWorkingDirectory(cast(char*) (AppPath(lpszPathObj) ~ \0));

/+      /* Set arguments */
        psl.SetArguments("-arg1 -arg2 -arg3"); /*UNCOMMENT THIS IF YOU WANT TO SET ARGUMENTS*/

        /* **** Other properties are available! ****
           Do not uncomment unless you define the other parameters.
           Read the Microsoft PSDK for more info.                   */
        psl.SetHotkey(wHotkey);
        psl.SetIDList(pidl);
        psl.SetRelativePath(pszPathRel, null); +/

        /* Query IShellLink for the IPersistFile interface for saving the 
           shortcut in persistent storage. */

        hres = psl.QueryInterface(&IID_IPersistFile, cast(void **) &ppf);

        if (SUCCEEDED(hres))
        { 
            WORD wsz[MAX_PATH];
 
            /* Ensure that the string is ANSI. */
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
 
            /* Save the link by calling IPersistFile::Save. */

            hres = ppf.Save(cast(wchar*) wsz, cast(int) true);
            ppf.Release();
        }
        psl.Release();
    }

    CoUninitialize(); /* Uninitialize the COM object */
    return hres;
}

Endless For Loop

DescriptionThis shows how to create an endless loop and break out of it if a given condition is met
Date/TimeMon Mar 14, 2005 11:03 pm
Posted byjcc7
void main
{
     for()
    {
        if( /*condition met */ )
        {
            printf("You entered the correct answer.\n");
            break; // exits the endless loop

        }
        else
        {
            // do something like print an error message
            printf("Sorry, try again\n"); // after this, we go over from the start
        }
    }
    printf("Bye!");
}


/* Submitted by anonymous contributor (Sat Jan 8, 2005 4:47 pm). */ 

Meta tags (__FILE__, __LINE__, etc.)

DescriptionThese "special tokens" embedded helpful information into the program at compile time.
Date/TimeMon Mar 14, 2005 11:01 pm
Posted byjcc7
/* Tested with DMD 0.118 */

import std.stdio;

int main (char[][] args)
{
    writef("Testing the D Code\n");
    writef("File:                %s\n",__FILE__);
    writef("Line:                %s\n",__LINE__);
    writef("Date:                %s\n",__DATE__);
    writef("Time:                %s\n",__TIME__);
    writef("TimeStamp:   %s\n",__TIMESTAMP__);

    return 0;


}
Based on digitalmars.D:19553.

uudecode

DescriptionD port of Clem Dye's uudecode.c
Date/TimeTue Mar 15, 2005 10:25 am
Posted byjcc7
/*
 
UUDECODE - a Win32 utility to uudecode single files.

Copyright (C) 1998 Clem Dye

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Modified 13 July 2001 by Clem Dye to allow any character in the range 0 to 
7 in the 'begin' statement within the header of the uuencoded file being 
decoded.

Ported to D: J C Calvarese, 14 May 2004 

Updated by J C Calvarese, 15 Mar 2004
* Recompiled with DMD 0.116
* Retested with the attachment to http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/19334.


************* Instructions ************* 

Compile:
dmd uudecode.d

Usage:
uudecode.exe d4676.txt 

(where d4676.txt would be the input file)

The input file should start with something like this: "begin 0644 stlport.zip"
and end with "end".

*/

import std.stream;

import std.string;


char[] toStringFromChar(char c)

/*  
    based on code posted by Helmut Leitner (helmut.leitner@chello.at), 
    23 Oct 2003 at http://www.digitalmars.com/drn-bin/wwwnews?D/18497 
*/

{
    char[] s = "?";
    s[0] = c;
    return s;
}




char DEC(char c)
{
    return (c - ' ') & 077;
}



char[] outname;


char[] uudecode (File f)
{
    int n;
    char ch;
    char[] buf, p;
    int pos;
    File outI = new File();
    
    
    do 
    {
          buf = f.readLine();
    }
    while (buf.length < 4 || buf[0..6] == "begin");
    pos = 6;
    
    while(pos != 0 &amp;& find(" 01234567", buf[pos..pos+1]) != -1) pos++;
    outname = buf[pos..buf.length];
    
    /* Create output file and set mode.  */ 
    outI.create(outname, FileMode.Out);
    
    /* For each input line:  */

    while(!f.eof)
    {
        buf = f.readLine();
        if (buf.length > 2 && buf[0..5] == "end") break;

        /* n is used to avoid writing out all the characters at the end of the file.  */

        pos = 0;

        n = DEC (buf[pos]);
        if (n <= 0)

        break;
        for (++pos; n > 0; /+ p += 4 +/ pos += 4, n -= 3)
        {
            p = buf[pos..buf.length];  
            if (n >= 3)
            {
                ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4; 
                outI.write(ch); //fputc(ch,outI);

                ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2; 
                outI.write(ch);  //fputc (ch,outI);
                ch = DEC (p[2]) << 6 | DEC (p[3]);
                outI.write(ch);  //fputc (ch,outI);

            }
            else
            {
                if (n >= 1)
                {
                    ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4; 
                    outI.write(ch);
                }
                if (n >= 2)
                {
                    ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2; 
                    outI.write(ch);
                }
            }
        }
    }
    outI.close();
    return outname;
}




int main(char[][] argv)
{
    File f;

    int argc = argv.length;
    debug for(int i; i<argv.length; i++)
    {
        printf("Argument %d: %.*s\n", i, argv[i]);
    }

    if (argc <= 1) {
            printf("Usage: %.*s <input file>\n", argv[0]); 
            return 1;
    }
    f = new File(argv[1]);

    uudecode(f);
    f.close();
    
    printf("Result decoded in %.*s\n", outname); 
    return 0;


}

Revised from digitalmars.D:4744.


Keywords

asm

DescriptionD allows the use of inline assembly language
Date/TimeThu Dec 2, 2004 6:48 pm
Posted byjcc7
void main()
{    
    int myint = 1234;
    char* mystring = "This number -> %d <- should be 1234\n";
    
    asm

    {
            push    dword ptr myint     ; // pointer to the integer variable declared in D 
            push    dword ptr mystring  ; // pointer into the C-style string declared in D
            call    printf              ; // call the printf function
    }


    /*
        This piece of code is the assembly equivalent of the C/D code
                
            int myint = 1234; 
            printf("This number -> %d <- should be 1234\n", myint);        
    */

}

Expected Output: This number -> 1234 <- should be 1234

Inspired by a code snippet found at in the NASM manual

For more details regarding asm blocks in D, check out the D Specification.

This example was tested on a x86 machine. I don't have any idea whether it'd work on any other platforms.


auto

DescriptionShows how auto objects differ from non-auto objects.
Date/TimeWed May 19, 2004 6:01 pm
Posted byjcc7
/* 

Demonstrates the usage of auto keyword.

Note how the auto objects are destroyed as soon as they go out of scope.

*/

class A
{
    private char[] name;
    
    char[] toString()
    {
        return name;
    }
    
    this(char[] s)
    {
        name = s;
        printf("'%.*s' created\n", name);
    }
    ~this()
    {
        printf("'%.*s' destroyed\n", name);
    }
}




void test2()
{
    auto A a2 = new A("test2");
}



void test3()
{
    A a3 = new A("test3");
}




void test4()
{
    auto A a4 = new A("test4");
}



void main()
{    
    A a = new A("main test");    
    printf("\tbegin main body\n");
    test2();
    test3();
    test4();
    printf("\tend main body (garbage collector will run next...)\n");
}

alias

DescriptionAn alias is used to add an additional name that can be used to call a type or function.
Date/TimeSat Oct 30, 2004 3:26 pm
Posted byjcc7
alias printf p;
alias char[] s;
alias void v;

v main(s[] a)
{
    p("Command used to start program: %.*s\n", a[0]);   
}

interface

DescriptionA simple example of a sophisticated abtraction tool.
Date/TimeSat Oct 30, 2004 3:26 pm
Posted byjcc7
/*

    File:       interface.d
    Author:     J C Calvarese, http://jcc_7.tripod.com/d/
                (Inspired by a newsgroup post by Hauke Duden, http://www.digitalmars.com/drn-bin/wwwnews?D/20956.)
    Purpose:    To demonstrate using an interface.

More information is available in the  D Specification, http://www.digitalmars.com/d/class.html#interface.

*/

interface I
{
    void a();
    void b();
}

class Impl : I
{
    void a()
    {
    }

    void b()
    {
    }

}



class Kid : Impl
{
    void b()
    {
        printf("overriden method\n\0");
    }

}



void main()
{  
    Kid k = new Kid();
    k.b();
}

dchar

DescriptionThe dchar type is like char, but bigger (corresponds to a UTF-32 Unicode code unit).
Date/TimeThu Dec 2, 2004 6:52 pm
Posted byjcc7
/*

    File:       dchar.d
    Author:     J C Calvarese, http://jcc_7.tripod.com/d/
    License:    Public Domain
    Purpose:    To show usage of the dchar character type.

*/

void main()
{ 
    dchar c = '0';
    
    if (c == '\U000000AA' || c == '\U000000BA') 
    
    /* 
        Character literals must be quoted (no "naked" escape sequences allowed) 
        If it was a string literal, quotes are optional.
    */

    
        printf("True\n");
    else
        printf("False\n");
}

final

DescriptionShows the usage of the final keyword on a class.
Date/TimeWed May 19, 2004 6:01 pm
Posted byjcc7
/* 
This example won't compile with either "final" compiled in: 
final.d(34): function toString cannot override final function toString  
*/ 
Apparently similar to Java's final.
/+final+/ class A
{
    private char[] name;
    
    /+final+/ char[] toString()
    {
        return name;
    }
    
    this(char[] s)
    {
        name = s;
        printf("'%.*s' created\n", name);
    }
    ~this()
    {
        printf("'%.*s' destroyed\n", name);
    }
}



class B: A /+ If class A is final this wouldn't work. +/
{
    char[] name;

    char[] toString() /* If this method were final in class A, this would cause a compile error. */
    {
        return name;
    }

    this(char[] s)
    {
        super(s);
    }
    ~this()
    {
        printf("'%.*s' destroyed\n", name);
    }
}




void main()
{    
}

goto

DescriptionD supports goto (but you're not required to use it).
Date/TimeWed May 19, 2004 6:02 pm
Posted byjcc7
/*

File:       goto.d
Date:       2004-02-16
Author:     by J C Calvarese, http://jcc_7.tripod.com/d/
License:    Public Domain
Purpose:    Shows the usage of goto and labels.

Why goto is part of the D programming language...
* goto is part of C, so it can facilitate porting of C/C++ code.
* goto is easy to implement.

Why you should avoid using goto...
* If you use too many goto's you can run into the spaghetti code syndrome.
* Using goto can make the code more difficult to understand for yourself and other.
* Usually, there's an easy way to do it without goto.

In the end, it's each programmer's choice, but I think that goto use should be minimized.

*/


void main()
{

thebeginning:
    printf("The beginning\n");

part1:
    printf("Part 1\n");

part2:
    printf("Part 2\n");
    goto part5;

part3:
    printf("Part 3\n");

part4:
    printf("Part 4\n");

part5:
    printf("Part 5\n");

theend:
    printf("The end\n");

}

return

DescriptionReturn exits a function
Date/TimeSat May 22, 2004 1:45 pm
Posted byjcc7
/* 
    Return exits a function. 
    If it's not a void function return allows you to return a value. 
*/

void f1() 
{
    printf("Running f1...\n");    
}

void f2() 
{ 
    bit itsAGoodIdea = true;

    printf("Running f2...\n");
    
    if(itsAGoodIdea)
    {
        f1();
        return; 
    }
    printf("Don't go there.\n");
}



void main()
{
    f2();
    printf("The end.\n");
}

/*

Output:

Running f2...
Running f1...
The end.

*/ 

Arrays

Delete All Keys From Associative Array

DescriptionShow a couple ways that all keys can be removed from an associate array.
Date/TimeSun Jun 27, 2004 10:03 pm
Posted byjcc7
/* starting post: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/4199 */

void main()
{
    char[][char[]] aA;
    printf("Fill in the array.\n");
    aA["a"] = "Apple";
    aA["b"] = "Book";
    aA["c"] = "Car";

    checkArray(aA);


    /* Clearing method from http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/4201 */

    printf("Clear out the items (implementation-dependent).\n");
    aA = null; 

    checkArray(aA);



    printf("\nFill in the array, again.\n");
    aA["a"] = "Apple";
    aA["b"] = "Book";
    aA["c"] = "Car";

    checkArray(aA);


    /* Clearing method from http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/4202 */

    printf("Removes it from the hash, doesn't delete the thing.\n");
    foreach(char[] key; aA.keys)
      delete aA[key];  
        
    checkArray(aA);
}



void checkArray(char[][char[]] assocArr)
{
    printf("%d\t", assocArr.length);

    if("a" in assocArr)
        printf("yes 'a'\t");
    else

        printf("no 'a'\t");
    if("b" in assocArr)
        printf("yes 'b'\t");
    else
        printf("no 'b'\t");
    if("c" in assocArr)
        printf("yes 'c'\t");
    else

        printf("no 'c'\t");
    if("d" in assocArr)
        printf("yes 'd'\n");
    else
        printf("no 'd'\n");
}

Various char arrays

DescriptionShows usage for some dynamic char arrays
Date/TimeSun Jun 27, 2004 10:05 pm
Posted byjcc7
import std.string;


char[][][] FieldValues;
char[][] Fields;
char[] myStr;

int[] nums;
int[][] morenums;



int main(char[][] args)
{

    int i;
    for(i=0; i<args.length; i++)
    {
        printf("\n" ~ args[i] ~ "\n");
    }

    nums.length = 5;
    nums[0] = 47;
    printf(toString(nums[0]));


    morenums.length = 10;
    morenums[0].length = 10;
    morenums[0][0] = 56;
    printf(toString(morenums[0][0]));


    Fields.length = 15;
    Fields[][0] = "Testing (2d)         blah blah blah.........\n";
    printf(Fields[][0]);

    printf("Hello.\n");

    myStr = "My string!";
    FieldValues.length = 10;
    FieldValues[0].length = 10;
    FieldValues[][0][0] = myStr; //"Testing.";    

    
    printf(FieldValues[][0][0]);


    return 0;

}

Dimensioning Static Arrays

DescriptionShows two ways that arrays can be dimensioned.
Date/TimeSun Jun 27, 2004 10:04 pm
Posted byjcc7
void main()
{

    /* 
        Believe it or not, but these two arrays        
        have the same dimensions. 
    */

    int[20][2] whatever;
    int whatever2[2][20];


    whatever[0][19] = 2;
    whatever2[0][19] = 2;

}


/* inspired by http://www.digitalmars.com/drn-bin/wwwnews?D/22869 */ 

Returning Arrays from Functions

DescriptionShows how to return arrays from functions.
Date/TimeSun Jun 27, 2004 10:04 pm
Posted byjcc7
int[] someFunction() /* dynamic array */ 
{
    int[] i;

    i.length = 5;
    i[0] = 1;
    i[1] = 1;
    i[2] = 2;
    i[3] = 3;
    i[4] = 5;
    return i;
}



struct fa_int5  /* struct wrapper */
{
    int[5] i; /* static array */
}


fa_int5 someFunction2()
{
    fa_int5 k;

    k.i[0] = 1;
    k.i[1] = 1;
    k.i[2] = 2;
    k.i[3] = 3;
    k.i[4] = 5;
    return k;
}



void main()
{
    int[] j = someFunction();
    fa_int5 m;

    m = someFunction2();
    int[5] n = m.i;
}

Using char[][] args

DescriptionA basic way to use the 'args' variable in the 'main' function.
Date/TimeSat Oct 30, 2004 3:25 pm
Posted byjcc7
/* Originally posted by Anonymous (2004-06-23 17:43:49) */

/*
to use, type:
[program name] -p [string to print]

This could be more complicated, but this'll give you an idea on
how to use arguments in your program.
*/
// the start of the program
int main(char[][] args)
{
    // check to make sure that the number of args is correct
    if(args.length < 2) // the first argument is the program name...

    {
        printf("No arguments given.\n");
        return 0;

    }

    for(int i = 0; i < args.length;i++)
    {
        if(args[i][0 .. 2] == "-p")
        {
            for(int ii = i+1; ii < args.length;ii++)
            {
                printf("%.*s ", args[ii]);
            }
            printf("\n");
        }
    }
    return 0;


}

Common Errors

Increasing the Size of a Dynamic Array

DescriptionYou can't use "r.length++;" to increase the size of a dynamic array.
Date/TimeFri May 14, 2004 9:49 pm
Posted byjcc7
/*     
    File:    inc.d
    Author:  J C Calvarese, http://jcc_7.tripod.com/d/
    Date:    2003/11/11
    Licence: Public domain
*/

int main()
{
    char[] r;
    int c;


    if(r.length < c) 
    r.length = r.length + 1;

    /* "r.length++;" isn't allowed. */


    return 0;

}

Using Objects

DescriptionObjects have to be initialized before they are used.
Date/TimeFri May 14, 2004 9:54 pm
Posted byjcc7
void main()
{  
   Object o;

    /* An access violation will occur if the following statement is omitted. */

    o = new Object(); 

   printf("%.*s", o.toString);
}

Printing a Slice from a String

DescriptionShows the trick for printing a slice from a character string.
Date/TimeFri May 14, 2004 10:18 pm
Posted byjcc7
int main( char [] [] args ) 
{ 
    char[] pr = "Hello Jon Thoroddsen !"[0..5];

    printf(pr ~ \0); 
    /* If the \0 isn't appended, you might get more characters than you expected. */

    return 1;
}

Based on code in post D:19840 by Jon Thoroddsen.


Delegates

DelegateTest.d

DescriptionA simple example of how to use delegates within objects, as delegates are usually used for GUI event handling such as in Delphi or C#. Example:
Date/TimeFri Jun 25, 2004 2:49 am
Posted byAnonymous
// Simple sample: how to use delegates within objects

import std.c.stdio;

// DelegateClass: a class with declared delegate function "printText"
class DelegateClass 
{
    public void delegate(char[] ) printText;
}

int main()
{
    // Function print

    void print(char[] text) { printf(text); }

    // Initialize a DelegateClass
    DelegateClass delclass = new DelegateClass();

        // Assign the delegate "printText" to function "print"
    delclass.printText = &print;

    // Call printText to test

    delclass.printText("HELLO\n");

    return 0;

}

Delegates

DescriptionIf you have an interface with only 1 function, use a delegate instead because it is more flexible.
Date/TimeThu Jul 29, 2004 9:53 pm
Posted byjcc7
import std.stdio;


interface Foo {
    int foo();
}

class MyClass : Foo {
    int foo() { 

        /* whatever */

        writefln("MyClass.foo() called") ;
        return 0;


    };
}


class ForgotFooClass {

  /* 
    Note that this class has the right functions to implement Foo, but
    I didn't add Foo interface to the list, so it's not compatible.
   */

int foo() {
 
        /* whatever */ 

        writefln("ForgotFooClass.foo() called") ;
        return 1; 
    };
}



class AnotherClass {
    int bar() { 
        /* whatever */ 
        writefln("AnotherClass.bar() called") ;
        return 2; 
    };
}


int main() {
    MyClass m = new MyClass;
    ForgotFooClass f = new ForgotFooClass;
    AnotherClass a = new AnotherClass;



//    doStuff1(a); /* can't call this */
/* 
Error:
 function doStuff1 (Foo f) does not match argument types (AnotherClass)
 cannot implicitly convert AnotherClass to Foo
*/

    doStuff1(m); /* legal call because MyClass derived from Foo */

//    doStuff1(f); /* can't call this because ForgotFooClass didn't derive from Foo */

//    doStuff2(f); /* can't call this */
/* 
Error:
 function doStuff2 (int delegate()d) does not match argument types (ForgotFooClass )
 cannot implicitly convert ForgotFooClass to int delegate()
*/

//    doStuff(a); /* can't call this because there is no matching function name for the Foo interface */

 /* 
  * these all work because the delegate can be extracted from the class without
  * it having to be part of the class declaration.
  */

    writefln();
    doStuff2(&m.foo);
    writefln();
    doStuff2(&f.foo);
    writefln();
    doStuff2(&a.bar);  /* the delegate can be a member with ANY name */

    return 0;


}

void doStuff1(Foo f) {
    writefln("doStuff1: f.foo() returned value = %d", f.foo()) ;
}

void doStuff2(int delegate() d) {
    writefln("doStuff2: d() returned value = %d", d()) ;
}

/* Original contribution by Russ Lewis. Changed based on suggestions by Blandger. */ 

Proper creation & use of stack delegates

DescriptionThis shows some basic example code using stack delegates.
Date/TimeThu Jul 29, 2004 10:05 pm
Posted byjcc7
import std.stdio;

/* A stack delegate, like any other delegate, is comprised of two pointers:
 * a funtion pointer, and a data pointer.  The data pointer is passed to the
 * function as an invisible argument (just like 'this' is passed to member
 * functions of a class.
 *
 * In the case of stack delegates, the pointer points to the stack frame where
 * the local variables are stored.  Modifying those variables inside a stack
 * delegate will modify the actual variables in the stack frame.
 */

void bar(void delegate() d) {
  writefln("--- bar( void delegate() d) called --- ");
  d();
}


void foo() {
    int a = 1;
    int b = 2;
    int c = 3;

    writefln("Start foo().
    Initial local values are a = %d, b = %d, c = %d", a,b,c);

    /* note that the stack delegate is declared as a delegate literal here.
     * Internally, the compiler declares an anonymous function, and the pointer
     * to the function is stored as the delegate's function pointer.
     */

    bar(delegate void() { a = 4; b = 5; c = 6; } );

    /* because bar() called the stack delegate, these values have changed */

    writefln("After calling bar(delegate) inside foo().
    Changed local values are a = %d, b = %d, c = %d", a,b,c);

    assert(a == 4);
    assert(b == 5);
    assert(c == 6);
}



int main() {

    foo();  

    return 0;

}

/* Original contribution by Russ Lewis. Changed based on suggestions by Blandger. */ 

Don't Return a Stack Delegate

DescriptionThis shows code that is BROKEN, namely returning a stack delegate from a function.
Date/TimeThu Jul 29, 2004 9:42 pm
Posted byjcc7
/* NOTE NOTE NOTE
 *
 * THIS CODE IS BROKEN.  This is an example of something that you
 * should NOT do!
 *
 * You can never return a stack delegate because the data pointer of that
 * delegate points to the stack frame where the delegate was created.  Once
 * you return from the function, that stack frame goes away and the memory
 * is reused by some other function.
 *
 * Most likely, when you call this stack delegate, your program won't crash
 * (since the pointer points to a valid address in the stack), but you will be
 * reading trash values, since the memory has been reused by some other
 * function.
 *
 * Of course, if one of the variables is a pointer, then you would crash when
 * you read & follow the pointer that is no longer valid.
 */

import std.stdio;

int delegate() foo() {
    int a = 1;
    int b = 2;

    writefln("int delegate() foo() is called. Locals a = %d, b = %d", a, b);
    writefln("BUG!  You must NEVER return a stack delegate!");

    return delegate int() { return a+b; };
}



int main() { 
    foo();
    return 0;

}

/* Original contribution by Russ Lewis. Changed based on suggestions by Blandger. */ 

Copyable stack delegates, implemented with structs and classes

DescriptionSome examples of how to copy a stack's local variables. Useful if you don't want to modify the original local variables, or if you want to return a stack delegates.
Date/TimeMon Jul 26, 2004 5:56 pm
Posted byAnonymous
/* This shows two different ways of creating a pseudo-copied stack delegate.
 *
 * The struct method is more efficient.  However, it is a bit harder to write & understand.
 * Also, it requires that you build a delegate by hand using a union, and that may not be
 * portable across all platforms or compilers.
 *
 * The class method is easier to understand and should be totally portable.  However,
 * it is less efficient because of the overhead inherent in a class.
 */

import std.c.stdio;

int RunDelegate(int delegate() d, int count) {
  assert(count > 0);

  int ret;
  for(int i=0; i<count; i++) {
    ret = d();
/*    printf("RunDelegate: cycle %d of %d returned %d\n", i+1,count,ret); */
  }
  return ret;
}


int main() {
  int delegate() d1 = getS(2);
  int delegate() d2 = getS(3);
  int delegate() d3 = getC(2);
  int delegate() d4 = getC(3);

  printf("main: RunDelegate(d1,4) returned %d\n", RunDelegate(d1,4));
  printf("main: RunDelegate(d1,4) returned %d\n", RunDelegate(d1,4));
  printf("main: RunDelegate(d2,4) returned %d\n", RunDelegate(d2,4));
  printf("main: RunDelegate(d2,4) returned %d\n", RunDelegate(d2,4));
  printf("main: RunDelegate(d3,4) returned %d\n", RunDelegate(d3,4));
  printf("main: RunDelegate(d3,4) returned %d\n", RunDelegate(d3,4));
  printf("main: RunDelegate(d4,4) returned %d\n", RunDelegate(d4,4));
  printf("main: RunDelegate(d4,4) returned %d\n", RunDelegate(d4,4));

  return 0;


}

/* both getS() and getC() return stack-copy style delegates.  In each case,
 * the delegate stores the argument to the function, and a counter.  Each time
 * that the delegate is called, the counter is multiplied by the argument, and
 * the result is returned.
 *
 * The end result is that, if you create a delegate with an argument of x and you
 * call it y times, then the y-th time it will return
 *     x^y
 */

/* getS() returns the delegate using the struct method;
 * getC() returns the delegate using the class method.
 */

struct GetS_Data {
  int base;
  int counter;
};

union delegate_union {
  int delegate() dg;
  struct {
    void *ptr;
    int function(void*) func;
  };
};

int delegate() getS(int base) {
  GetS_Data *data = new GetS_Data[1];
  data.base = base;
  data.counter = 1;

  delegate_union u;
  u.func = function int(void *arg) {
             GetS_Data *data = cast(GetS_Data*)arg;
             data.counter *= data.base;
             return data.counter;
           };
  u.ptr = data;

  return u.dg;
}


class GetC_Data {
  int counter;
  int base;

  this(int base) {
    this.base = base;
    this.counter = 1;
  }

  int func() {
    counter *= base;
    return counter;
  }
}


int delegate() getC(int base) {
  GetC_Data data = new GetC_Data(base);
  return &data.func;
}

Copyable stack delegates (with writefln)

DescriptionSome examples of how to copy a stack's local variables. Useful if you don't want to modify the original local variables, or if you want to return a stack delegates.
Date/TimeThu Jul 29, 2004 9:59 pm
Posted byjcc7
/* This shows two different ways of creating a pseudo-copied stack delegate.
 *
 * The struct method is more efficient.  However, it is a bit harder to write & understand.
 * Also, it requires that you build a delegate by hand using a union, and that may not be
 * portable across all platforms or compilers.
 *
 * The class method is easier to understand and should be totally portable.  However,
 * it is less efficient because of the overhead inherent in a class.
 */

import std.stdio;

int RunDelegate(int delegate() d, int count) {
    assert(count > 0);

    int ret;
    for(int i=0; i<count; i++) {
        ret = d();
//        writefln("RunDelegate: cycle %d of %d returned %d\n", i+1,count,ret);
    }
    return ret;
}


int main() {
    int delegate() d1 = getS(2);
    int delegate() d2 = getS(3);
    int delegate() d3 = getC(2);
    int delegate() d4 = getC(3);

    writefln("main: RunDelegate(d1,4) returned %d", RunDelegate(d1,4));
    writefln("main: RunDelegate(d1,4) returned %d", RunDelegate(d1,4));

    writefln("main: RunDelegate(d2,4) returned %d", RunDelegate(d2,4));
    writefln("main: RunDelegate(d2,4) returned %d", RunDelegate(d2,4));

    writefln("main: RunDelegate(d3,4) returned %d", RunDelegate(d3,4));
    writefln("main: RunDelegate(d3,4) returned %d", RunDelegate(d3,4));

    writefln("main: RunDelegate(d4,4) returned %d", RunDelegate(d4,4));
    writefln("main: RunDelegate(d4,4) returned %d", RunDelegate(d4,4));

    return 0;


}

    /* both getS() and getC() return stack-copy style delegates.  In each case,
     * the delegate stores the argument to the function, and a counter.  Each time
     * that the delegate is called, the counter is multiplied by the argument, and
     * the result is returned.
     *
     * The end result is that, if you create a delegate with an argument of x and you
     * call it y times, then the y-th time it will return
     *     x^y
     */

    /* getS() returns the delegate using the struct method;
     * getC() returns the delegate using the class method.
     */

struct GetS_Data {
    int base;
    int counter;
};


union delegate_union {
    int delegate() dg;
    struct {
        void *ptr;
        int function(void*) func;
    };
};


int delegate() getS(int base) {
    GetS_Data *data = new GetS_Data[1];
    data.base = base;
    data.counter = 1;

    delegate_union u;
    u.func = function int(void *arg) {
             GetS_Data *data = cast(GetS_Data*)arg;
             data.counter *= data.base;
             return data.counter;
           };
    u.ptr = data;

    return u.dg;
}


class GetC_Data {
    int counter;
    int base;

    this(int base) {
        this.base = base;
        this.counter = 1;
    }

    int func() {
        counter *= base;
        return counter;
    }
}


int delegate() getC(int base) {
    GetC_Data data = new GetC_Data(base);
    return &data.func;
}

/* Original contribution by Russ Lewis. Changed based on suggestions by Blandger. */ 

Delegate 1

DescriptionA delegate allows assigning a non-static nested function to a variable.
Date/TimeWed Aug 11, 2004 6:55 pm
Posted byjcc7
/+ from http://www.digitalmars.com/d/function.html#closures +/

int delegate() dg;

void main()
{  
   int a = 7;
   int foo() { return a + 3; }

   dg = &foo;
   int i = dg();  /* i is set to 10 */

}

Delegate 2

DescriptionA more complicated delegate example.
Date/TimeWed Aug 11, 2004 6:56 pm
Posted byjcc7
/* from http://www.digitalmars.com/d/function.html#closures */

struct Foo
{   
    int a = 7;
    int bar() { return a; }
}


int foo(int delegate() dg)
{
    return dg() + 1;
}

void main()
{
    int x = 27;
    int abc() { return x; }
    Foo f;
    int i;

    i = foo(&abc);      /* i is set to 28 */

    i = foo(&f.bar);    /* i is set to 8 */
}

Foreach

Foreach on a class

DescriptionYou can define how your class iterates through foreach with an opApply method.
Date/TimeMon May 3, 2004 12:20 am
Posted byjcc7
/*  

foreach was added in DMD 0.71
http://www.digitalmars.com/d/statement.html#foreach

*/

class Foo
{
   uint array[2];

   int opApply(int delegate(inout uint) dg)
   {   
      int result = 0;




      for (int i = 0; i < array.length; i++)
      {
         result = dg(array[i]);
         if (result)
            break;
      }
      return result;
   }
}




void test()
{
   Foo a = new Foo();

   a.array[0] = 73;
   a.array[1] = 82;

   foreach (uint u; a)
   {
      printf("%d\n", u);
   }
}



int main()
{
    test();
    return 0;

}

Foreach with an inout

DescriptionAn "inout" can be used to update the original elements.
Date/TimeMon May 3, 2004 12:19 am
Posted byjcc7
/*  

foreach was added in DMD 0.71
http://www.digitalmars.com/d/statement.html#foreach


"inout" can be used to update the original elements.

*/



void test()
{
    static uint[2] a = [7, 8];

    foreach (inout uint u; a)
    {
        u++;
    }

    foreach (uint u; a)
    {
        printf("%d\n", u);
    }
}




int main()
{
    test();
    return 0;

}

Foreach with a string literal

DescriptionForeach aggregates can be string literals, which can be accessed as char, wchar, or dchar arrays.
Date/TimeMon May 3, 2004 12:19 am
Posted byjcc7
/*  

foreach was added in DMD 0.71
http://www.digitalmars.com/d/statement.html#foreach


Aggregates can be string literals, which can be accessed as 
char, wchar, or dchar arrays.

*/



void test()
{
    foreach (char c; "ab")
    {
        printf("'%c'\n", c);
    }

    foreach (wchar w; "xy")
    {
        wprintf("'%c'\n", w);
    }
}



int main()
{
    test();
    return 0;

}

Foreach with a char[]

DescriptionShows using foreach with a dynamic char array.
Date/TimeMon May 3, 2004 12:20 am
Posted byjcc7
/*

Inspired by 
http://www.digitalmars.com/drn-bin/wwwnews?D/25475

*/

import std.string;

void main()
{
   char[] names = "200 digitalmars.com InterNetNews NNRP server INN 2.3.2 ready (posting ok).
Sending List request.....
215 Newsgroups in form \"group high low flags\".
c++ 0000003792 0000000001 y
D 0000025479 0000000001 y
D.gnu 0000000488 0000000001 y
DMDScript 0000000040 0000000001 y
c++.beta 0000000357 0000000001 y
c++.stlsoft 0000000188 0000000001 y
c++.wxwindows 0000000172 0000000001 y";

   char[][] ch = split(names,"\n");
   foreach(char[] c; ch)
   {
      printf("%.*s = \n", c);
   }
}

Foreach with key and value pairs

DescriptionYou can iterate across associative arrays with both key and value, and also capture the index for static/dynamic arrays.
Date/TimeMon May 3, 2004 12:24 am
Posted byjcc7
/*

foreach was added in DMD 0.71
http://www.digitalmars.com/d/statement.html#foreach

This example was originally posted by csauls.

*/

void main() {
    int[char[]] map;
    float[] array;

    map["abc"] = 123;
    map["def"] = 456;
    map["xyz"] = 890;

    array ~= 1.23;
    array ~= 3.14;

    printf("Iterating over map...\n");
    foreach (char[] key, int value; map) {
        printf("\t%.*s => %d\n", key, value);
    }

    printf("Iterating over array...\n");
    foreach (int index, float value; array) {
        printf("\t%d => %f\n", index, value);
    }
}

Associative array of strings

DescriptionForeach with an associative array of dynamic strings (uses alias, too)
Date/TimeMon May 3, 2004 12:20 am
Posted byjcc7
/* ******* ******* *******

Foreach with an associative array of strings

foreach was added in DMD 0.71
http://www.digitalmars.com/d/statement.html#foreach

(This example was inspired on an example posted by csauls from comments by larsivi.)

******* ******* ********/



/* 
    This alias makes it a little easier to see what's going on with the 
    dynamic strings (a/k/a "char[]"). 
*/
alias char[] string; 



void main() {

    /* create an associative array called "map" */

    string[string] map; 


    /* 
        The associate array is populated like this:
        map[key] = value 
    */
    
    map["abc"] = "apple";
    map["def"] = "bee";
    map["xyz"] = "cat";


    /* 
        The foreach is used to determine the contents of 
        the associative array.
    */

    printf("Iterating over map...\n");
    foreach (string key, string value; map) 
    {
        printf("\t%.*s => %.*s\n", key, value);
    }
}

Function Literals

Function Literal Assignment

DescriptionFunction Literals enable embedding anonymous functions directly into expressions.
Date/TimeMon Mar 14, 2005 11:12 pm
Posted byjcc7
/* based on http://www.prowiki.org/wiki4d/wiki.cgi?DWiki/FunctionLiterals 
   which was copied from http://dlanguage.netunify.com/11 */

int function(char c) fp;

void main() 
{ 
    static int foo(char c) 
    { 
        return 6; 
    } 
    fp = &foo;

    printf("%d", fp('A')); 
}

Function Literal / Anonymous Function

DescriptionFunction Literals enable embedding anonymous functions directly into expressions.
Date/TimeMon Mar 14, 2005 11:12 pm
Posted byjcc7
/* based on http://www.prowiki.org/wiki4d/wiki.cgi?DWiki/FunctionLiterals 
   which was copied from http://dlanguage.netunify.com/11 */

int function(char c) fp;

void main() 
{ 
    fp = function int(char c) 
    { 
        return 6;
    }; //note the semi-colon at the end 


    printf("%d\n", fp('A'));
}

For more details, see the D Spec.


Handling errors

DBC: basic design by contract

DescriptionImplements specialized square_root used in doc example (with updated code to reflect dmd >= 0.102) and one-based lookup table.
Date/TimeMon Oct 11, 2004 8:22 am
Posted byLynn
import std.stdio;

import std.math;

/* compile with dmd test.d */

void main ()
{
  long rc = GetMaxChapInBook(3);
  writefln("rc: ", rc);

  rc = square_root(16);
  writefln("rc: ", rc);
}


/* Specialized sqrt that requires an integer
 * that is an actual squared value (e.g. 1,4,9,16,etc)
 * Corresponds to DBC documentation with casts so that
 * it will compile with dmd >= 0.102
 * http://www.digitalmars.com/d/dbc.html
 */
long square_root(long x)
in 
{
  assert(x >= 0);

}
out (result)
{
  assert((result * result) == x);
}
body
{
  return cast(long)std.math.sqrt(cast(double)x);
}


/* One-based lookup table. An index of 0 or > 9 is rejected.
 * The return value rc is constrained to be between 1 and 50.
 * Note that "result" used in doc isn't reserved word or required.
 * Could also be done with enum??
 */
ushort GetMaxChapInBook(in ushort bk)
in { assert((bk >= 1) && (bk <= 9)); }

out (maxChap) { assert((maxChap >= 1) && (maxChap <= 50)); }

body {
  return chapsInBook[bk];
}


ushort[] chapsInBook = [
  0,  50, 40, 27, 36, 34, 24, 21,  4, 31     // 0-9

];

Try/Catch/Finally

Descriptioncatch that error (don't let it catch you!)
Date/TimeSat Oct 30, 2004 3:29 pm
Posted byjcc7

Try-Finally is also available in Java and C#.

import std.asserterror;

int main()
{
    
    try
    {
        whatever();
    }
    catch(AssertError)
    {  
        printf("Whoa!  Hold on there.  An assertion failed.\n\n");      
    }
    finally

    {
        
        /* 
            The finally block executes to allow clean-up of items 
            allocated in the try block.
        */
        
        printf("This would happen after the errors are dealt with (if there are any errors).\n\n");
    }
    printf("If something happened, it wasn't enought of a problem to end the program.\n\n");
    
    return 0;


}


void whatever()
{  
    assert(0); /* comment out this line to see what happens if no error occurs */

}

Operator Overloading

Currency

DescriptionA currency object featuring some operator overloading.
Date/TimeWed May 19, 2004 5:51 pm
Posted byjcc7
/*
    Title:   Currency with Operator Overloading
    File:    currency.d
    Author:  J C Calvarese, http://jcc_7.tripod.com/d/
    Date:    2004/01/03
    Licence: Public domain


    TEST version: outputs more information to the console during run.
*/


import std.string;
import std.math;




char[] leadingZeros(byte num, byte digits)
/* by J C Calvarese, also in locales2.d and with.d */
{ 
    char[] buffer;
    byte diff;
    
    buffer = toString(num);
    if (buffer.length < digits) 
    {
        diff = digits - buffer.length;
        for(int i=0; i < diff; i++)
          buffer = "0" ~ buffer;
    } 
    return buffer;
}




char[] toStringFromDouble(double d)
{
    return toStringFromDouble(d, 2); /* defaults to 2 decimal places */ 
}

char[] toStringFromDouble(double d, int decPlaces)
{
    return toStringFromDouble(d, decPlaces, "."); /* separator defaults to period */ 

}

char[] toStringFromDouble(double i, int decPlaces, char[] sep)
{  
    int whole;
    int dec;
    double decPart;
    
    whole = cast(int) i;
    version(TEST) printf("whole: %d\n", whole);

    decPart = (i - whole) * pow(cast(real) 10, cast(uint) decPlaces);
    version(TEST) printf("decPart: %lf\n", decPart);
    
    dec = cast(int) (decPart);
    version(TEST) printf("dec: %d\n", dec);
    return toString(i) ~ sep ~ leadingZeros(dec, decPlaces);
}




class Currency
{   
    /* Read property ("get-ter") */
    double value() {return intValue;}
    
    /* Write property ("set-ter") */
    double value(double v) {return intValue = v;}

    
    this(double v)
    {
        version(TEST) printf("An instance of the Currency object is created.\n\n");
        intValue = v;
        intSeparator = ".";
        intDecPlaces = 2;
    }
    
    this()
    {
        this(0);

    }
    
    char[] toString() { return toStringFromDouble(intValue, intDecPlaces, intSeparator);}



    /* operator overloading */

    Currency opAdd(Currency m, Currency n)
    {  
        Currency t;
        t.value = m.value + n.value;
        return t;
    }

    Currency opAddAssign(Currency m)
    {  
        intValue += m.value;
        return this;
    }


    private 
    {
        double intValue;
        double intDecPlaces;
        char[] intSeparator; /* decimal, period (U.S.), comma (Some non-U.S. locations) */

    }
}



void main()
{ 
    Currency c = new Currency();  
    printf("\n\t\t\t\t\t\t%.*s\n", c.toString);

    printf("Change the value:\t\t\t\t");
    c.value = 100.75;
    printf("%.*s\n", c.toString);

    Currency c2 = new Currency(26.12);
    printf("\t\t\t\t\t\t%.*s\n", c2.toString);

    printf("Change the value:\t\t\t\t");
    c2.value = 6.25;
    printf("%.*s\n", c2.toString);

    printf("Change the value (operator overloading):\t");
    c2 += c; /* requires operator overloading */

    printf("%.*s\n\n", c2.toString);
}

Currency (Using with)

DescriptionA currency object featuring some operator overloading (uses with).
Date/TimeWed May 19, 2004 5:52 pm
Posted byjcc7
/*
    Title:   Currency with Operator Overloading (using "with")
    File:    with.d
    Author:  J C Calvarese, http://jcc_7.tripod.com/d/
    Date:    2004/01/03
    Licence: Public domain


    TEST version: outputs more information to the console during run.
*/


import std.string;
import std.math;




char[] leadingZeros(byte num, byte digits)
/* by J C Calvarese, also in locales2.d */
{ 
    char[] buffer;
    byte diff;
    
    buffer = toString(num);
    if (buffer.length < digits) 
    {
        diff = digits - buffer.length;
        for(int i=0; i < diff; i++)
          buffer = "0" ~ buffer;
    } 
    return buffer;
}




char[] toStringFromDouble(double d)
{
    return toStringFromDouble(d, 2); /* defaults to 2 decimal places */ 
}

char[] toStringFromDouble(double d, int decPlaces)
{
    return toStringFromDouble(d, decPlaces, "."); /* separator defaults to period */ 

}

char[] toStringFromDouble(double i, int decPlaces, char[] sep)
{  
    int whole;
    int dec;
    double decPart;
    
    whole = cast(int) i;
    version(TEST) printf("whole: %d\n", whole);

    decPart = (i - whole) * pow(cast(real) 10, cast(uint) decPlaces);
    version(TEST) printf("decPart: %lf\n", decPart);
    
    dec = cast(int) (decPart);
    version(TEST) printf("dec: %d\n", dec);
    return toString(i) ~ sep ~ leadingZeros(dec, decPlaces);
}




class Currency
{   
    /* Read property ("get-ter") */
    double value() {return intValue;}
    
    /* Write property ("set-ter") */
    double value(double v) {return intValue = v;}

    
    this(double v)
    {
        version(TEST) printf("An instance of the Currency object is created.\n\n");
        intValue = v;
        intSeparator = ".";
        intDecPlaces = 2;
    }
    
    this()
    {
        this(0);

    }
    
    char[] toString() { return toStringFromDouble(intValue, intDecPlaces, intSeparator);}



    /* operator overloading */

    Currency opAdd(Currency m, Currency n)
    {  
        Currency t;
        t.value = m.value + n.value;
        return t;
    }

    Currency opAddAssign(Currency m)
    {  
        intValue += m.value;
        return this;
    }


    private 
    {
        double intValue;
        double intDecPlaces;
        char[] intSeparator; /* decimal, period (U.S.), comma (Some non-U.S. locations) */

    }
}



void main()
{ 
    Currency c; // = new Currency();  

    with(c = new Currency())
    { 
        printf("\n\n\t\t\t\t\t\t%.*s\n", toString);
    
        printf("Change the value\t\t\t\t");
        value = 100.75;
        printf("%.*s\n", toString);
    }
    
    Currency c2;    
    with(c2 = new Currency(26.12))
    { 
        printf("\t\t\t\t\t\t%.*s\n", toString);
    
        printf("Change the value\t\t\t\t");
        value = 6.25;
        printf("%.*s\n", toString);
    
        printf("Change the value (operator overloading)\t\t");
        c2 += c; /* requires operator overloading */

        printf("%.*s\n\n", toString);
    }
}

opCall

DescriptionShows how an opCall can be assigned to allow using C++-style new-ing on a class.
Date/TimeWed May 19, 2004 5:50 pm
Posted byjcc7

Based on digitalmars.D:1539

import std.string;

class A
{
    this(uint x)
    {
        num = x;
    }
    
    char[] toString() 
    {
        return std.string.toString(num);
    }
    
    private uint num;
    
    
    
    static A opCall(uint x)
    {
        /* This overload allow the shorter C++ syntax for 
           "new"-ing the class. */

        return new A(x);
    }
}

void main()
{
    /* and you can create class objects the in a c++ syntax */
    A a = A(500); 
    
    A a2 = new A(567);

    printf("Number: %.*s\n", a.toString());
    printf("Number: %.*s\n", a2.toString());
}

Byte.d

DescriptionA very simple class that shows the use of operator overloadings.
Date/TimeFri Jun 11, 2004 9:47 am
Posted byAnonymous
/*
 * ***************************************************************************
 * Byte.d - Show operator overloading and some properties
 * Bruno A. Costa (brunoacf AT elitemail DOT org)
 * ******************************************************************************
 */

class Byte
{
private:
    byte _value;
public:

        this ( ) {
        _value = 0;


    }

    this (byte bt) {
    _value = bt;
    }

    this (Byte bt) {
        _value = bt.value;
    }

    // Set Property
    byte value (byte bt) {
        return _value = bt;
    }

    // Set Property

    byte value (Byte bt) {
        return _value = bt.value;
    }

    // Get Property
    byte value ( ) {
        return _value;
    }

    // Overload operator ==

    int opEquals (byte bt) {
        return _value == bt;
    }

    // Overload operator ==
    int opEquals (Byte bt) {
        return _value == bt.value;
    }

    // Overload operator + (Byte + Byte)

    Byte opAdd (Byte bt) {
        Byte newbt = new Byte();
        newbt.value = _value + bt.value;
        return newbt;
    }

    // Overload operator + (Byte + byte)
    Byte opAdd (byte bt) {
        Byte newbt = new Byte();
        newbt.value = _value + bt;
        return newbt;
    }

    // Overload operators > >= < <=

    int opCmp (Byte bt) {
         return (_value - bt.value);
    }

}

int main ( )
{

    Byte b = new Byte(2);
    Byte b2 = new Byte(2);
    byte b4 = 10;


    if (b == b2) printf ("b == b1\n");      // call opEquals

    Byte b3 = new Byte (b + b2);            // call opAdd (Byte)

    if (b3 < b2) printf ("b3 > b2\n");      // call opCmp

    b = b2 + b4;                                    // call opAdd (byte)

    printf ("b2 + b4 = %i\n", b.value);

    // Show values returned from opCmp( )
    // 1 == true; 0 == false
    printf ("b2 > b3: %i\n", (b2 > b3) );
    printf ("b2 < b3: %i\n", (b2 < b3) );
    printf ("b2 >= b3: %i\n", (b2 >= b3) );
    printf ("b2 <= b3: %i\n", (b2 <= b3) );

    return 0;


}

switch / case

Switch-Case Construct

DescriptionThe switch-case construct can be a good way to replace a complicated series of if/else if/else if/else.
Date/TimeMon Mar 14, 2005 11:13 pm
Posted byjcc7
D
int main()
{
    int i;

    switch(i)
    {
        case 0: 

            printf("i is zero"); 
            break;  
            /* Without each "break", 
               the flow will fall-through. */

        case 1: 
            printf("i is one");  
            break;

        case 2:
            printf("i is one");  
            break;
    
        default: 
            printf("i is one");  
            break;
    }
    return 0;


}
QuickBASIC Dim i%

Select Case i%
Case 0: Print "i is zero"
Case 1: Print "i is one"
Case 2: Print "i is two"
Case 3: Print "i is three"
Case Else: Print "i is something else"
End Select
Output i is zero

The Twelve Days of Christmas

DescriptionPrints the lyrics to the Twelve Days of Christmas
Date/TimeMon Mar 14, 2005 11:09 pm
Posted byjcc7
/*

The Twelve Days of Christmas

File:      twelve.d
Author:    Justin C. Calvarese
Website:   http://jcc_7.tripod.com/d/
License:   Public Domain

Produces the lyrics of the 12 Days of Christmas (all twelve verses)

*/


const char[] I1 = "On the ";
const char[] I2 = " day of Christmas, my true love gave to me:";

const char[] D1 = "A Partridge in a Pear Tree.";
const char[] D2 = "Two Turtle Doves, and";
const char[] D3 = "Three French Hens,";

const char[] D4 = "Four Calling Birds,";
const char[] D5 = "Five Golden Rings,";
const char[] D6 = "Six Geese a Laying,";

const char[] D7 = "Seven Swans a Swimming,";
const char[] D8 = "Eight Maids a Milking,";
const char[] D9 = "Nine Ladies Dancing,";

const char[] D10 = "Ten Lords a Leaping,";
const char[] D11 = "Eleven Pipers Piping,";
const char[] D12 = "Twelve Drummers Drumming,";




void println(char[] s)
{
    printf(cast(char*) (s ~ "\n\0")); /* A simple \n\0 (without quotes) is valid in D, but d2html won't handle it */
}



int main (char[][] args) 
{
    char[] s;

    for (int e=1; e<=12; e++)
    {
        for (int d=e; d>0; d--)
        {   
            s = "";

            if (d==e)
            {
                s = I1;
                
                switch(d)
                {
                    case 1:  s ~= "first"; break;
                    case 2:  s ~= "second"; break;
                    case 3:  s ~= "third"; break;
                    case 4:  s ~= "fourth"; break;
                    case 5:  s ~= "fifth"; break;
                    case 6:  s ~= "sixth"; break;
                    case 7:  s ~= "seventh"; break;
                    case 8:  s ~= "eighth"; break;
                    case 9:  s ~= "ninth"; break;
                    case 10: s ~= "tenth"; break;    
                    case 11: s ~= "eleventh"; break;
                    default: s ~= "twelveth"; break;
                }
                s ~= I2;
                println(s);
            }

            switch (d)
            {
                case 12: println(D12); break;
                case 11: println(D11); break;
                case 10: println(D10); break;
                case 9:  println(D9); break;
                case 8:  println(D8); break;
                case 7:  println(D7); break;
                case 6:  println(D6); break;
                case 5:  println(D5); break;
                case 4:  println(D4); break;
                case 3:  println(D3); break;
                case 2:  println(D2); break;
                default: println(D1); println(""); break;
            }
        }
    }
    return 0;



}

The Twelve Days of Christmas (Reprise)

DescriptionAnother example that prints the lyrics to the Twelve Days of Christmas.
Date/TimeMon Mar 14, 2005 11:10 pm
Posted byjcc7
/*
The Twelve Days of Christmas
 
File:           twelve_days_2.d
Author:         J C Calvarese, http://jcc_7.tripod.com/d/
Modified by:    Larry Cowan
License:        Public Domain
 
Produces the lyrics of the 12 Days of Christmas (all twelve verses).
It has a few subtle changes such as a break-less switch statement.
*/
 

const char[] I1 = "On the ";

const char[] I2 = " day of Christmas, my true love gave to me:";
const char[] D1 = "A Partridge in a Pear Tree.";
const char[] D2 = "Two Turtle Doves, and";

const char[] D3 = "Three French Hens,";
const char[] D4 = "Four Calling Birds,";
const char[] D5 = "Five Golden Rings,";

const char[] D6 = "Six Geese a Laying,";
const char[] D7 = "Seven Swans a Swimming,";
const char[] D8 = "Eight Maids a Milking,";

const char[] D9 = "Nine Ladies Dancing,";
const char[] D10 = "Ten Lords a Leaping,";
const char[] D11 = "Eleven Pipers Piping,";

const char[] D12 = "Twelve Drummers Drumming,";
 
 
 
void println(char[] s)
{
    printf(cast(char*) (s ~ "\n\0")); /* A simple \n\0 (without quotes) is valid in D, but d2html won't handle it */

}
 
 
 
int main (char[][] args)
{
    char[] s;
 
    for (int e=1; e<=12; e++)
    {
        s = I1;
               
        switch(e)       /* ...keeping the cases separate... */

        {
            case 1:  s ~= "first"; break;
            case 2:  s ~= "second"; break;
            case 3:  s ~= "third"; break;
            case 4:  s ~= "fourth"; break;
            case 5:  s ~= "fifth"; break;
            case 6:  s ~= "sixth"; break;
            case 7:  s ~= "seventh"; break;
            case 8:  s ~= "eighth"; break;
            case 9:  s ~= "ninth"; break;
            case 10: s ~= "tenth"; break;   
            case 11: s ~= "eleventh"; break;
            default: s ~= "twelveth"; break;
        }
        s ~= I2;
        println(s);
 
        switch (e)     /* ...and without the break statements... */

        {
            case 12: println(D12);
            case 11: println(D11);
            case 10: println(D10);
            case 9:  println(D9);
            case 8:  println(D8);
            case 7:  println(D7);
            case 6:  println(D6);
            case 5:  println(D5);
            case 4:  println(D4);
            case 3:  println(D3);
            case 2:  println(D2);
            default: println(D1); println(""); break;
        }
    }
    return 0;



}

Templates

Struct Template

DescriptionThis template technique involving a struct is apparently undocumented.
Date/TimeThu Jun 17, 2004 8:26 pm
Posted byjcc7
struct foo(T)
{
   T x;

   void getsize()
   {
      printf("%d\n", x.sizeof);
   }
}



void main(char[][] args)
{
   foo!(int) y;
   y.getsize();

   int i;
   printf("%d\n", i.sizeof);

   foo!(creal) r;
   r.getsize();
   printf("%d\n", r.sizeof);
}

Based on: digitalmars.D:3895


Interface Template

DescriptionShows how to use an interface template
Date/TimeMon Jun 21, 2004 9:20 pm
Posted byjcc7

It wasn't mentioned in the docs, but I had a slight inkling that it might be the case that one could have InterfaceTemplates using the same syntax as ClassTemplates (ie class ClassName(T) : [superclass [, interfaces] ). The following example compiled and ran correctly, outputting "1\n4\n" as expected. Perhaps this warrants a mention in the documentation under Templates, alongside "Class Templates"?

Source: digitalmars.D:3828

interface Foo(T)
{
   int aFunction(T anArgument);
}

class Bar(T) : Foo!(T)
{
   int aFunction(T anArgument)
   {
      return anArgument.size;
   }
}


int main(char[][] args)
{
   Bar!(ubyte) one = new Bar!(ubyte);
   Bar!(int) two = new Bar!(int);

   ubyte oneVar = 16;
   int twoVar = 400000;

   printf("%i\n%i\n", one.aFunction(oneVar), two.aFunction(twoVar));

   return 0;


}

Iterator

DescriptionAn iterator with a list class
Date/TimeThu Jul 29, 2004 2:49 pm
Posted byjcc7
/*
 * Copyright (c) 2004
 * Sean Kelly
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Author makes no representations about
 * the suitability of this software for any purpose. It is provided
 * "as is" without express or implied warranty.
 */


//
// simple list type

//
// this is defined kind of oddly to get around scoping problems
//
template List( Ty )
{
public:
    alias Ty        Value;
    alias size_t    Size;


    class Node
    {
    public:
        alias List!(Ty).Value   Value;
    
        this()
        {
            prev = this;
            next = this;
        }

        this( Value v )
        {
            val = v;
            this();
        }

    private:
        Value   val;
        Node    prev,
                next;
    }


    class Iterator
    {
    public:
        alias List!(Ty).Value   Value;
    
        this( Node n )
        {
            ref = n;
        }

        Iterator opAddAssign( int unused )
        {
            ref = ref.next;
            return this;
        }

/*
        Iterator opPostInc()
        {
            iterator tmp( ref );
            ref = ref.next;
            return tmp;
        }
*/
        Iterator opSubAssign( int unused )
        {
            ref = ref.prev;
            return this;
        }
/*
        Iterator opPostDec()
        {
            iterator tmp( ref );
            ref = ref.prev;
            return tmp;
        }
*/
        int opEquals( Iterator rhs )
        {
            return ref == rhs.ref;
        }

        void val( Value v )
        {
            ref.val = v;
        }

        Value val()
        {
            return ref.val;
        }
        
    private:
        Node    ref;
    }


    class Container
    {
    public:
        alias List!(Ty).Iterator Iterator;
        alias List!(Ty).Value    Value;
        alias List!(Ty).Size     Size;
        
        this()
        {
            m_head  = new Node();
            m_size  = 0;


        }
    
        Size size()
        {
            return m_size;
        }
    
        bit empty()
        {
            return m_size == 0;

        }
    
        Iterator begin()
        {
            return new Iterator( m_head.next );
        }
    
        Iterator end()
        {
            return new Iterator( m_head );
        }

        Value front()
        {
            return m_head.next.val;
        }

        Value back()
        {
            return m_head.prev.val;
        }

        void pushFront( Value val )
        {
            insert( begin(), val );
        }

        void pushBack( Value val )
        {
            insert( end(), val );
        }

        Iterator insert( Iterator pos, Value val )
        {
            Node n = new Node( val );
            n.next = pos.ref;
            n.prev = pos.ref.prev;
            pos.ref.prev.next = n;
            pos.ref.prev = n;
            ++m_size;
            return --pos;
        }

    protected:
        Node    m_head;
        Size    m_size;
    }
}



//
// default iterator definitions that apply
// to all user-defined containers
//
template IterImpl( Ty )
{
    alias Ty            Container;
    alias Ty.Iterator   Iterator;    
    alias Ty.Value      Value;
    alias Ty.Size       Size;

    Iterator begin( Container cont )
    {
        return cont.begin();
    }

    Iterator end( Container cont )
    {
        return cont.end();
    }
}



//
// iterator specialization for primitive array
//
template IterImpl( Ty : Ty[] )
{
    alias Ty[]      Container;
    alias Ty        Value;
    alias size_t    Size;
    
    class Iterator
    {
    public:
        this( Ty* pos )
        {
            m_pos = pos;
        }

        Iterator opAddAssign( int unused )
        {
            if( m_pos )
                ++m_pos;
            return this;
        }

        Iterator opSubAssign( int unused )
        {
            if( m_pos )
                --m_pos;
            return this;
        }

        int opEquals( Iterator rhs )
        {
            return m_pos == rhs.m_pos;
        }

        void val( Value val )
        {
            if( m_pos )
                *m_pos = val;
        }

        Value val()
        {
            return m_pos ? *m_pos : Ty.init;
        }
    
    private:
        Value*  m_pos;
    }

    Iterator begin( Container cont )
    {
        return new Iterator( cont.length ? &cont[0] : null );
    }

    Iterator end( Container cont )
    {
        return new Iterator( cont.length ? &cont[0] + cont.length : null );
    }
}



//
// convenience wrappers to reduce type length
//
template Iterator( Ty )
{
    alias IterImpl!(Ty).Iterator Iterator;
}


template begin( Ty )
{
    alias IterImpl!(Ty).begin begin;
}



template end( Ty )
{
    alias IterImpl!(Ty).end end;
}


//
// slightly lame sample algorithm that only works for int value types
//
template print( Iter )
{
    void print( Iter begin, Iter end )
    {
        for( ; begin != end; ++begin )
            printf( "%d\n", begin.val );
    }
}



int main( char[][] args )
{
    alias List!(int).Container  IntList;
    alias int[]                 IntArray;

    IntList     list    = new IntList();
    IntArray    array;

    list.insert( list.begin(), 1 );
    list.insert( list.begin(), 2 );
    list.insert( list.begin(), 3 );
    
    array.length = 3;
    array[0] = 7;
    array[1] = 8;
    array[2] = 9;

    Iterator!(IntList)  l_begin = begin!(IntList)( list ),
                        l_end   = end!(IntList)( list );
    
    Iterator!(IntArray) a_begin = begin!(IntArray)( array ),
                        a_end   = end!(IntArray)( array );

    print!(Iterator!(IntList))( l_begin, l_end );
    printf( "\n" );
    print!(Iterator!(IntArray))( a_begin, a_end );
    return 0;


}

Source: digitalmars.D:7583


Internal templates

DescriptionShows how templates within classes can be useful.
Date/TimeFri Sep 10, 2004 12:03 pm
Posted byAnonymous
// by Joey Peters

/*
This should show you how templates in classes are useful and how they
could (or should) be used with mixins.

Practicly, this is mostly useful for when you're writing your own containers.
*/

class List(T) {
public:
    // hold an array with items
    T[] data;
    this() {}
    // constructs with data set
    this(T[] d) {
        data = d;
    }
    // convert the array automatically, but still allow it's functionality.

    template as(NT) {
        // copy completely copies an array, but with a new type
        NT[] copy() {
            NT[] ret;
            foreach(T i; data) {
                ret.length = ret.length + 1;
                // cast it to the new type
                ret[ret.length - 1] = cast(NT) i;
            }
            return ret; 
        }
    }
    // mix in it's own type, so the functionality is still there for

    // it's own type.
    mixin as!(T);
}

void main() {
    // first, we have two types of lists, integer lists and double lists
    alias List!(int) iList;
    alias List!(double) dList;
    // then, we make an integer list

    iList list1 = new iList;
    // list 2 is a copy of list 1
    iList list2 = new iList(list1.copy());
    // list 3 is a double list, and a copy of list 2
    dList list3 = new dList(list2.as!(double).copy());
    // magic :) you may want to overload a few things to make this look more elegant etc.

    return;
}

Simple Template

DescriptionDemonstrates using ! for template instantiation (DMD 0.77+).
Date/TimeMon May 3, 2004 12:15 am
Posted byjcc7
/*

    File:    template_d077.d
    Author:  J C Calvarese, http://jcc_7.tripod.com/d/
    Date:    2004/01/03
    Purpose: demonstrates using templates in D (using syntax introduced in DMD 0.77)
    
*/

template TStat(T)
{ 
    
    T avg(T a, T b)
    { 
        return (a + b) / 2;
    }
    
    T avg(T a[])
    {
        T b;
        b = 0;  /* If b isn't initialized, then "nan" will be returned. */

        
        for (int i = 0; i < a.length; i++) 
          b += a[i];
        
        return b / a.length;
    }
}


void main()
{  
    int i, j, avg1, avg2;
    int m[];    
    double avg3, avg4;
    double d, e;
    double n[];

    
    i = 6;
    j = 8;
    
    m.length = 4;
    m[0] = 2;
    m[1] = 3;
    m[2] = 4;
    m[3] = 3;
    
    avg1 = TStat!(int).avg(i, j);
    avg2 = TStat!(int).avg(m[]);

    printf("avg1: %d\navg2: %d\n", avg1, avg2);
    
    d = 7.75;
    e = 7.50;
    
    n.length = 3;
    n[0] = 3.13;
    n[1] = 3.15;
    n[2] = 3.19;
    
    avg3 = TStat!(double).avg(d, e);
    avg4 = TStat!(double).avg(n[]);
        
    printf("avg3: %lf\navg4: %lf\n", avg3, avg4);
}

Template Constructors

DescriptionUsing a template to create class constructors
Date/TimeMon May 3, 2004 12:05 am
Posted byjcc7
/*

From: "Robert" 
Newsgroups: D
Subject: Re: template constructors?
Date: Fri, 30 Jan 2004 08:08:31 +0900
Organization: Digital Mars
Xref: digitalmars.com D:22767

*/

class Foo(T) {
    private static T _bar;

    static this() {
        // initialize _bar

    }
    static ~this() {
        // finalize _bar
    }
    static void baz() {
        // use _bar

    }
}

int main() {
    Foo!(int).baz();
    return 0;

}

Template Functions

DescriptionTemplate Functions
Date/TimeMon May 3, 2004 12:04 am
Posted byjcc7
/+

From: "Ben Hinkle"
Newsgroups: D
Subject: Re: template functions
Date: Mon, 23 Feb 2004 14:19:47 -0500
Xref: digitalmars.com D:24532

+/


/+
Take Two. Collections are just waay to much fun to putter around with 
Here's an example that results in calls that look like
  TmixCollectionTypes!(Object,String).addAll(foo,bar);
when you want to copy from one contained type to another.
More details:
+/

interface Collection(T) { // a cheesy Collection
    T getItem();
    void addItem(T x);
}

template TmixCollectionTypes(S,T) {
    void addAll(Collection!(S) x, Collection!(T) y) {
        x.addItem(y.getItem()); // you get the idea...

  }
}

class LinkedList(T): Collection!(T) { // a cheesy list
    T getItem() { return item; }
    void addItem(T x) { item=x; }
    T item;
}

class String {}


int main(char[][] argv)
{
    Collection!(Object) foo = new LinkedList!(Object);
    Collection!(String) bar = new LinkedList!(String);
    TmixCollectionTypes!(Object,String).addAll(foo,bar);
    return 0;

}

Multiple Inheritance with template 'bolt-ins'

DescriptionI've been experimenting a little, most of this is taken from Andy Freisens streams.d which doesn't appear to be on the web anymore. His is a very good example, this is trivial please expand on it!
Date/TimeMon May 3, 2004 12:03 am
Posted byjcc7
/* 

Originally posted by Q in March 2004. 

Apparently based on 
http://www.digitalmars.com/drn-bin/wwwnews?D/25856 

*/

import std.c.stdio;

interface Vehicle {
    
    void drive();
    void stop();
    
}


class Car (T) : T , Vehicle{

    void drive() { puts("driving on land");} 
    void stop () { puts("stopping on land"); } 
    
    void driveOnRoad() { puts("driving on road"); }
}



class Boat (T) : T , Vehicle { 
    
    void drive () { puts("driving on water"); } 
    void stop () { puts("stopping on water"); } 
    
    void floatOnWater() { puts("floating on water"); }     
}


alias Car!( Boat!(Object ) ) CarBoat;
alias Boat!( Car!(Object ) ) BoatCar;    

void main ( ) {
    
    CarBoat x = new CarBoat;
    x.floatOnWater();
    x.driveOnRoad();
    x.drive();
    
    puts("\n");
    
    BoatCar y = new BoatCar;
    y.floatOnWater();
    y.driveOnRoad();
    y.drive();    
}

Variable Arguments

DescriptionTemplate to facilitate using variable argument lists
Date/TimeMon May 3, 2004 12:05 am
Posted byjcc7
/+

From: "Ben Hinkle" 
Newsgroups: D
Subject: Re: Variable numbers of function parameters?
Date: Tue, 2 Mar 2004 09:05:06 -0500
Xref: digitalmars.com D:25034



+/



private import std.c.stdio;
template va_array(T)
{
   T[] va_array(uint* ptr)
   {
      T* args = cast(T*)(cast(va_list)ptr + uint.size);
      return args[0 .. *ptr];
   }
}

template new_array(T)
{
   T[] new_array(uint n,...)
   {
      return va_array!(T)(&n).dup;
   }
}

// user code
void test(int[] x)
{
   printf("last element: %d\n",x[x.length-1]);
}


int main()
{
   test(new_array!(int)(3, 1,2,3));
   return 0;


}

Template RTTI

DescriptionOf questionable usefulness in it's current incantation, but templates do have some support for runtime type identification.
Date/TimeSun May 23, 2004 2:03 pm
Posted byjcc7
class Thing(T)
{
    
}
 
void main()
{
    Thing!(int) thing = new Thing!(int);
   
    printf("%.*s\n", thing.classinfo.name);

}


/*
Output:

Thing
*/ 

From digitalmars.D:1842


Versioning

Built-in Versions

DescriptionDetermine your compile environment at compile time.
Date/TimeSat Oct 30, 2004 3:24 pm
Posted byjcc7
See also the D Specification.
/*
    File:       versioning.d
    Date:       2004-02-20
    Author:     J C Calvarese, http://jcc_7.tripod.com/d/
    Purpose:    Shows the use of the version statement.    
*/

import std.c.stdio;

void main()
{ 
    
    version(DigitalMars) printf("Digital Mars is the compiler vendor.\n");

    version(linux)
    {
        printf("You're compiling on Linux.\n");
    }
    else

    {
        version(Windows)
        {
            printf("You're compiling on Windows:\t");
            version(Win32) printf("Microsoft 32 bit Windows systems\n");
            version(Win64) printf("Microsoft 64 bit Windows systems\n");
        }
        else /* There is probably how a Palm or Mac implementation would be indicated. */

        {
            version(Palm) printf("You're compiling on Palm.\n");
            version(Mac)  printf("You're compiling on Mac.\n");
        }
    }
    
    version(X86) printf("Processor: Intel or AMD 32 bit\n");
     
    version(AMD64) printf("Processor: AMD 64 bit processor\n");     

    version(LittleEndian)   printf("The byte order is least significant first.\n");
    version(BigEndian)      printf("The byte order is most significant first.\n");

    version(D_InlineAsm)    printf("Inline assembler is implemented.\n");
    version(none)           printf("This code is always disabled.\n");
    
}

Using versions to store multiple programs in one file

DescriptionRather than having multiple programs, just have one that compiles for a variety of settings.
Date/TimeThu Sep 23, 2004 9:31 pm
Posted byjcc7
/*
Version.d - the versioning example.
Written by Ameer Armaly, and in the public domain.
*/
//you can version for different os's like so:
version(linux
{
import std.c.linux.linux;
}
version(Win32)
{
import std.c.windows.windows;
}
//or for different environments

version(fast)
{
//whatever makes it runf aster
}
version(small)
{
//whatever makes it smaller
}

Contributed by Anonymous on Sun Jul 25, 2004.


Compile time versioning

DescriptionShows how to do versioning in files at compile time.
Date/TimeThu Sep 23, 2004 9:30 pm
Posted byjcc7
// By Joey Peters

// pass -version=free to dmd
version(Free) {
 version = FeatureA;
} else {
 version = FeatureA;
 version = FeatureB;
}


void main() {
 // every version has this.
 version(FeatureA) {
   printf("Hello world!");
 }
 // only the non free has this
 version(FeatureB) {
   printf("Deluxe!");
 }
}


/*
The equivalent of #define CONTRACT would be:
version = CONTRACT
Though, I must add you should not use capitals like you're used to ;)
The equivalent of #ifdef ... #endif is:
version(...) {

}
The equivalent of #ifdef ... #else #endif is:
version(...) {

} else {

}
*/ 

DFL

DflMiniCalc

DescriptionDemonstrates (VERY) simple calculator with two buttons and three input fields. Equivalent to Win32 api MiniCalc example.
Date/TimeWed Dec 22, 2004 8:41 am
Posted byLynn
// To compile:
// dmd DflMiniCalc.d dfl.lib -L/exet:nt/su:windows:4.0

private import dfl.all;

private import std.string;

class MiniCalcForm: Form
{
  this()
  {
    text = "DflMiniCalc";
    CreateControls();       

    acceptButton = plusButton;
  }
    
  private void CreateControls()
  {
    size = Size(120, 150);  // Overall form size

    plusButton = new Button;
    plusButton.parent = this;
    plusButton.text = "Plus";
    plusButton.left = 10;
    plusButton.size = Size(50, 25);
    plusButton.click ~= &PlusClick;

    minusButton = new Button;
    minusButton.parent = this;
    minusButton.text = "Minus";
    minusButton.left = 60;
    minusButton.size = Size(50, 25);
    minusButton.click ~= &MinusClick;

    firstNumberText = new TextBox;
    firstNumberText.parent = this;
    firstNumberText.text = "170";
    firstNumberText.location = Point(10, 30);
    firstNumberText.size = Size(100, 20);

    secondNumberText = new TextBox;
    secondNumberText.parent = this;
    secondNumberText.text = "252";
    secondNumberText.location = Point(10, 55);
    secondNumberText.size = Size(100, 20);

    resultNumberText = new TextBox;
    resultNumberText.parent = this;
    resultNumberText.text = "";
    resultNumberText.location = Point(10, 80);
    resultNumberText.size = Size(100, 20);
  }
    
  private void PlusClick(Object sender, EventArgs ea)
  {
    GetNumbers();
    result = num1 + num2;
    resultNumberText.text = std.string.toString(result);
  }

  private void MinusClick(Object sender, EventArgs ea)
  {
    GetNumbers();
    result = num1 - num2;
    resultNumberText.text = std.string.toString(result);
  }

  private void GetNumbers()
  {
    char[] firstValue = firstNumberText.text;
    char[] secondValue = secondNumberText.text;
    num1 = atoi(firstValue);
    num2 = atoi(secondValue);
  }

  private TextBox firstNumberText;
  private TextBox secondNumberText;
  private TextBox resultNumberText;
  private Button  plusButton;
  private Button  minusButton;
  private long    num1;
  private long    num2;
  private long    result;
}


int main()
{
  Application.run(new MiniCalcForm);
    
  return 0;

}

Resizable Dialog

DescriptionDemonstrates DialogApp that adjusts the position and size of several controls when the overall application window is resized. (Caveat: DFL newbie so this may not be best way to accomplish)
Date/TimeWed Dec 22, 2004 4:04 pm
Posted byLynn
// To compile:

// dmd DflTest dfl.lib -L/exet:nt/su:windows:4.0

private import std.string;

private import dfl.form, dfl.event, dfl.drawing, dfl.application;
private import dfl.button, dfl.textbox, dfl.treeview;


class ResizableForm: Form
{
this()
{
  text = "DflResizeTest";

  CreateControls();
}

const int DEFAULT_LEFT          = 2;
const int DEFAULT_TOP           = 2;

const int DEFAULT_HEIGHT_ADJUST = 45;
const int DEFAULT_WIDTH_ADJUST  = 10;
const int DEFAULT_RIGHT         = 504;

const int DEFAULT_BOTTOM        = 404;
const int CHAPTREE_WIDTH        = 122;
const int DEFAULT_BUTTON_HEIGHT = 25;

const int DEFAULT_BUTTON_WIDTH  = ((CHAPTREE_WIDTH / 2) - 3);
const int SEARCHBUTTON_HEIGHT   = DEFAULT_BUTTON_HEIGHT;
const int BOOKSBUTTON_WIDTH     = DEFAULT_BUTTON_WIDTH;

const int HELPBUTTON_WIDTH      = DEFAULT_BUTTON_WIDTH;
const int HELPBUTTON_LEFT       = (DEFAULT_RIGHT 
                                  - (DEFAULT_BUTTON_WIDTH + 5));
const int SEARCHBUTTON_WIDTH    = DEFAULT_BUTTON_WIDTH;

const int SEARCHBUTTON_LEFT     = (DEFAULT_BUTTON_WIDTH + 4);
const int SEARCHWORDS_LEFT      = (CHAPTREE_WIDTH + 0);
const int CHAPTREE_HEIGHT       = (DEFAULT_BOTTOM 
                                  - (DEFAULT_BUTTON_HEIGHT 
                                  + DEFAULT_HEIGHT_ADJUST));

const int CHAPTREE_TOP          = (DEFAULT_BUTTON_HEIGHT + 4);
const int OPTIONSBUTTON_WIDTH   = 60;
const int OPTIONSBUTTON_LEFT    = (DEFAULT_RIGHT 
                                  - (OPTIONSBUTTON_WIDTH 
                                  + DEFAULT_BUTTON_WIDTH + 8));

const int TEXTVIEWER_WIDTH      = (DEFAULT_RIGHT 
                                  - (CHAPTREE_WIDTH + 3));
const int SEARCHWORDS_WIDTH     = (DEFAULT_RIGHT 
                                  - (CHAPTREE_WIDTH 
                                  + OPTIONSBUTTON_WIDTH 
                                  + DEFAULT_BUTTON_WIDTH + 8));

private void CreateControls()
{
  size = Size((DEFAULT_RIGHT - DEFAULT_LEFT) + DEFAULT_WIDTH_ADJUST, 
              DEFAULT_BOTTOM - DEFAULT_TOP);  // Overall form size

  resize ~= &ResizeForm;

  booksButton = new Button;
  booksButton.parent = this;
  booksButton.text = "Books";
  booksButton.location = Point(DEFAULT_LEFT, DEFAULT_TOP);
  booksButton.size = Size(DEFAULT_BUTTON_WIDTH, 
                          DEFAULT_BUTTON_HEIGHT);

  helpButton = new Button;
  helpButton.parent = this;
  helpButton.text = "Help";
  helpButton.size = Size(DEFAULT_BUTTON_WIDTH, 
                         DEFAULT_BUTTON_HEIGHT);

  optionsButton = new Button;
  optionsButton.parent = this;
  optionsButton.text = "Options";
  optionsButton.size = Size(DEFAULT_BUTTON_WIDTH, 
                            DEFAULT_BUTTON_HEIGHT);

  searchButton = new Button;
  searchButton.parent = this;
  searchButton.text = "Search";
  searchButton.location = Point(SEARCHBUTTON_LEFT, DEFAULT_TOP);
  searchButton.size = Size(DEFAULT_BUTTON_WIDTH, 
                           DEFAULT_BUTTON_HEIGHT);

  searchWordsTextBox = new TextBox;
  searchWordsTextBox.parent = this;
  searchWordsTextBox.text = "searchWordsTextBox";
  searchWordsTextBox.location = Point(SEARCHWORDS_LEFT, 
                                      DEFAULT_TOP);
  searchWordsTextBox.multiline = false;
  searchWordsTextBox.readOnly = false;

  viewerTextBox = new TextBox;
  viewerTextBox.parent = this;
  viewerTextBox.text = "viewerTextBox";
  viewerTextBox.location = Point(CHAPTREE_WIDTH, CHAPTREE_TOP);
  viewerTextBox.multiline = true;
  viewerTextBox.readOnly = true;
  viewerTextBox.wordWrap = true;

  chapSelectorTree = new TreeView;
  chapSelectorTree.parent = this;
  chapSelectorTree.location = Point(DEFAULT_LEFT, CHAPTREE_TOP);

  ResizeForm(null, null);
}
  

private void ResizeForm(Object sender, EventArgs ea)
{
  Size formClientSize = clientSize();
  Rect formBounds     = bounds();
  int  formHeight     = formClientSize.height;
  int  formWidth      = formClientSize.width;
   
  int helpButtonLeft    = (formWidth  - (DEFAULT_BUTTON_WIDTH + 5));
  int chapTreeHeight    = (formHeight - (DEFAULT_BUTTON_HEIGHT + 10));
  int optionsButtonLeft = (formWidth  - (OPTIONSBUTTON_WIDTH 
                           + DEFAULT_BUTTON_WIDTH + 8));
  int textViewerWidth   = (formWidth  - (CHAPTREE_WIDTH + 3));
  int searchWordsWidth  = (formWidth  - (CHAPTREE_WIDTH 
                           + OPTIONSBUTTON_WIDTH 
                           + DEFAULT_BUTTON_WIDTH + 8));

  searchWordsTextBox.size = Size(searchWordsWidth, 
                                 DEFAULT_BUTTON_HEIGHT);
  viewerTextBox.size = Size(textViewerWidth, chapTreeHeight);
  chapSelectorTree.size = Size(CHAPTREE_WIDTH, chapTreeHeight);

  optionsButton.location = Point(optionsButtonLeft, DEFAULT_TOP);
  helpButton.location = Point(helpButtonLeft, DEFAULT_TOP);
}


private Button    booksButton;
private Button    helpButton;
private Button    optionsButton;
private Button    searchButton;

private TreeView  chapSelectorTree;
private TextBox   searchWordsTextBox;

private TextBox   viewerTextBox;
}

int main()
{
  Application.run(new ResizableForm);
  
  return 0;

}

MiniCalcWithRmb

DescriptionExtension of MiniCalc with 'Plus' button having ContextMenu when RMB (right mouse button) clicked. There is a common handler for all 3 RMB menu-items, and argument "sender" is used to determine which menu-item was clicked.
Date/TimeMon Dec 27, 2004 5:47 pm
Posted byLynn
// To compile:
// dmd DflTest dfl.lib -L/exet:nt/su:windows:4.0

private import std.string;

private import dfl.form, dfl.event, dfl.drawing, dfl.application;
private import dfl.button, dfl.textbox, dfl.menu, dfl.control;


class MiniCalcForm: Form
{
  this()
  {
    text = "DflMiniCalc";

    CreateOtherControls();    

    CreatePlusButtonWithRmbMenu();    

    acceptButton = _plusButton;
  }
  
  private void CreateOtherControls()
  {
    size = Size(120, 150);  // Overall form size

    _minusButton = new Button;
    _minusButton.parent = this;
    _minusButton.text = "Minus";
    _minusButton.left = 60;
    _minusButton.size = Size(50, 25);
    _minusButton.click ~= &onMinusClick;

    _firstNumberText = new TextBox;
    _firstNumberText.parent = this;
    _firstNumberText.text = "170";
    _firstNumberText.location = Point(10, 30);
    _firstNumberText.size = Size(100, 20);

    _secondNumberText = new TextBox;
    _secondNumberText.parent = this;
    _secondNumberText.text = "252";
    _secondNumberText.location = Point(10, 55);
    _secondNumberText.size = Size(100, 20);

    _resultNumberText = new TextBox;
    _resultNumberText.parent = this;
    _resultNumberText.text = "";
    _resultNumberText.location = Point(10, 80);
    _resultNumberText.size = Size(100, 20);
  }
  
  private void CreatePlusButtonWithRmbMenu()
  {
    _plusButton = new Button;
    _plusButton.parent = this;
    _plusButton.text = "Plus";
    _plusButton.left = 10;
    _plusButton.size = Size(50, 25);
    _plusButton.click ~= &onPlusClick;

    _plusButton.contextMenu = new ContextMenu;

    MenuItem miDouble = new MenuItem;
    miDouble.text = "Double";
    miDouble.click ~= &onPbcmHandler;
    miDouble.index = 0;


    _plusButton.contextMenu.menuItems.add(miDouble);

    MenuItem miTriple = new MenuItem;
    miTriple.text = "Triple";
    miTriple.click ~= &onPbcmHandler;
    miTriple.index = 1;
    _plusButton.contextMenu.menuItems.add(miTriple);

    MenuItem miSeparator = new MenuItem;
    miSeparator.text = "-";
    miSeparator.index = 2;
    _plusButton.contextMenu.menuItems.add(miSeparator);

    MenuItem miHalf = new MenuItem;
    miHalf.text = "Half";
    miHalf.click ~= &onPbcmHandler;
    miHalf.index = 3;
    _plusButton.contextMenu.menuItems.add(miHalf);
  }
  
  void onPbcmHandler(Object sender, EventArgs ea)
  {
    GetNumbers();

    MenuItem mi = cast(MenuItem)sender;
    char[] label = mi.text;
    debug char* _dbgLabel = label;

    switch (label) 
    {
      case "Double":
           _num1 += _num1;
           break;
      
      case "Triple":
           _num1 += (_num1 + _num1);
           break;
      
      case "Half":
           _num1 /= 2;
           break;
    }
    _firstNumberText.text = std.string.toString(_num1);
  }
    
  private void onPlusClick(Object sender, EventArgs ea)
  {
    GetNumbers();
    _result = _num1 + _num2;
    _resultNumberText.text = std.string.toString(_result);
  }

  private void onMinusClick(Object sender, EventArgs ea)
  {
    GetNumbers();
    _result = _num1 - _num2;
    _resultNumberText.text = std.string.toString(_result);
  }

  private void GetNumbers()
  {
    char[] firstValue = _firstNumberText.text;
    char[] secondValue = _secondNumberText.text;
    _num1 = atoi(firstValue);
    _num2 = atoi(secondValue);
  }

  private TextBox _firstNumberText;
  private TextBox _secondNumberText;
  private TextBox _resultNumberText;
  private Button  _plusButton;
  private Button  _minusButton;
  private long    _num1;
  private long    _num2;
  private long    _result;
}


int main()
{
  Application.run(new MiniCalcForm);
  
  return 0;

}

DflTextBox with Selection reverse video

DescriptionDemonstrates how to find and select text in single-line and multi-line TextBox's such that the found characters are highlighted in reverse video. For the multi-line TextBox, the selected chars aren't visible, so scrollToCaret is used to bring it into vi
Date/TimeMon Dec 27, 2004 7:23 pm
Posted byLynn
import std.stdio, std.string;

import dfl.form, dfl.textbox, dfl.button, dfl.event, dfl.application, dfl.drawing;

class MainForm: Form 
{ 
  TextBox single, multi; 
  this() 
  { 
    Button sbtn; 
    with(sbtn = new Button) 
    { 
      text = "&Find 'ment for'"; 
      parent = this; 
      click ~= &sbtn_click; 
    } 
    
    with(single = new TextBox) 
    { 
      left = sbtn.right + 4; 
      text = "Open Source Development for D Open Source Development for D"; 
      hideSelection = false; 
      parent = this; 
    } 
    
    Button mbtn; 
    with(mbtn = new Button) 
    { 
      top = 40; 
      text = "&Find 'for D 6'"; 
      parent = this; 
      click ~= &mbtn_click; 
    } 
    
    with(multi = new TextBox) 
    { 
      text = "Line 1 Open Source Development for D 111\r\n"

             "Line 2 Open Source Development for D 222\r\n"
             "Line 3 Open Source Development for D 333\r\n"
             "Line 4 Open Source Development for D 444\r\n"
             "Line 5 Open Source Development for D 555\r\n"
             "Line 6 Open Source Development for D 666\r\n"
             "Line 7 Open Source Development for D 777\r\n"

             "Line 8 Open Source Development for D 888\r\n"
             "Line 9 Open Source Development for D 999"; 
      hideSelection = false; 
      bounds = Rect(mbtn.right + 4, mbtn.top, 200, 60); 
      multiline = true; 
      acceptsReturn = true; 
      parent = this; 
    } 
  } 
  private void sbtn_click(Object sender, EventArgs ea) 
  { 
    int foundOffset = std.string.rfind(single.text, "ment for"); 
    if(foundOffset != -1) { 
      single.select(foundOffset, 8);  // 8 is len of 'ment for'

    } 
  } 
  private void mbtn_click(Object sender, EventArgs ea) 
  { 
    int foundOffset = std.string.rfind(multi.text, "for D 6"); 
    if(foundOffset != -1) { 
      multi.select(foundOffset, 7); // 7 is len of 'for D 6' 

      multi.scrollToCaret(); 
    } 
  } 
}

void main()
{
  Application.run(new MainForm);
}

ToolTips and ListBox having Object entries

DescriptionListBox comprised of objects (rather than text strings). When onHover handler reached, the selected object from the ListBox is determined and its toString confirms which entry has the mouse over it.
Date/TimeFri Dec 31, 2004 12:59 pm
Posted byLynn
import std.string;

import dfl.all;

class Birthday: Object
{
  private int _year, _month, _day;

  this(int y, int m, int d) {
    _year = y;
    _month = m;
    _day = d;
  }
  char[] toString() {
    return (monthNames[_month] 
            ~ " " ~ std.string.toString(_day)
            ~ "," ~ std.string.toString(_year));
  }
  const char[][] monthNames = ["", "January", "February", "March", 
          "April", "May", "June", "July", "August", "September", 
          "October", "November", "December"];
}


class MainForm: Form 
{ 
  ToolTip _ttip; 
  ListBox _myList; 
   
  this() 
  { 
    if(!Control.supportsMouseTracking) {
      MessageBox.show("Please install Internet Explorer 5.5 or higher."); 
    }
    size = Size(350, 200);
    _ttip = new ToolTip; 
    
    _myList = new ListBox; 
    _myList.items.add(new Birthday(1776,  7,  4)); 
    _myList.items.add(new Birthday(1926,  5, 16)); 
    _myList.items.add(new Birthday(1927, 12, 31)); 
    _myList.items.add(new Birthday(1951,  5, 19)); 
    _myList.items.add(new Birthday(1952, 10, 18)); 
    _myList.items.add(new Birthday(1952,  7, 24)); 
    _myList.items.add(new Birthday(1967,  2, 16)); 
    _myList.items.add(new Birthday(1977, 11, 14)); 
    _myList.parent = this; 
    _myList.mouseHover ~= &myList_hover; 
  } 
   
  void myList_hover(Object sender, MouseEventArgs ea) 
  { 
    int index = _myList.indexFromPoint(ea.x, ea.y); 
    if(index != -1) {
      Object o = _myList.items.opIndex(index);
      Birthday bd = cast(Birthday)o;
      text = "Hovering over item: " ~ bd.toString(); 
      _ttip.setToolTip(_myList, "Item: " ~ bd.toString()); 
      _ttip.active = true; // Show the tip now. 

    } 
    else { 
      _ttip.setToolTip(_myList, null); 
    } 
  } 
}

void main()
{
  Application.run(new MainForm);
}

Checkboxes

DescriptionDemonstrates getting and setting the state of the checkboxes.
Date/TimeThu Dec 16, 2004 6:24 pm
Posted byjcc7

This program requires Vathix's DFL. I've tested it with DFL 0.7 and DMD 0.106.

Batch file:

@echo off
dmd checkboxes.d -L/exet:nt/su:windows:4.0 ..\dfl.lib -I..
checkboxes.exe
pause
import dfl.all;


/* Program constants */

const char[] defaultPath = "C:\\Program Files\\jcc7";
const char[] pgmName = "Checkbox Example";



int main()
{
    Form frmMain;    
    CheckBox chk1, chk2, chk3, 
      chk4, chk5, chk6, chk7, 
      chk8;      
    TextBox txtPath;
    Label lblInstruct;
    Button btnBrowse, btnInstall, btnCheckAll, btnCheckNone;


    void bntInstall_onClick(Object sender, EventArgs ea)
    {
        char[] installPath = txtPath.text ~ "\\";
        MessageBox.show(installPath, "txtPath");
        
        if(chk1.checkState == CheckState.CHECKED)
          MessageBox.show("Part 1 checked", pgmName);
        
        if(chk2.checkState == CheckState.CHECKED)
          MessageBox.show("Part 2 checked", pgmName);

        if(chk3.checkState == CheckState.CHECKED)
          MessageBox.show("Part 3 checked", pgmName);
        
        if(chk4.checkState == CheckState.CHECKED)
          MessageBox.show("Part 4 checked", pgmName);
        
        if(chk5.checkState == CheckState.CHECKED)
          MessageBox.show("Part 5 checked", pgmName);
        
        if(chk6.checkState == CheckState.CHECKED)
          MessageBox.show("Part 6 checked", pgmName);
        
        if(chk7.checkState == CheckState.CHECKED)
          MessageBox.show("Part 7 checked", pgmName);
        
        if(chk8.checkState == CheckState.CHECKED)
          MessageBox.show("Part 8 checked", pgmName);        
    }
    

    void bntCheckNone_onClick(Object sender, EventArgs ea)
    {
        chk1.checkState(CheckState.UNCHECKED);
        chk2.checkState(CheckState.UNCHECKED);
        chk3.checkState(CheckState.UNCHECKED);
        chk4.checkState(CheckState.UNCHECKED);
        chk5.checkState(CheckState.UNCHECKED);
        chk6.checkState(CheckState.UNCHECKED);
        chk7.checkState(CheckState.UNCHECKED);
        chk8.checkState(CheckState.UNCHECKED);
    }
    
    void bntCheckAll_onClick(Object sender, EventArgs ea)
    {
        chk1.checkState(CheckState.CHECKED);
        chk2.checkState(CheckState.CHECKED);
        chk3.checkState(CheckState.CHECKED);
        chk4.checkState(CheckState.CHECKED);
        chk5.checkState(CheckState.CHECKED);
        chk6.checkState(CheckState.CHECKED);
        chk7.checkState(CheckState.CHECKED);
        chk8.checkState(CheckState.CHECKED);
    }  


    
    void bntBrowse_onClick(Object sender, EventArgs ea)
    {
        MessageBox.show("You clicked on browse.", pgmName);
    }



    frmMain = new Form;
    frmMain.text = "Checkboxes";
    frmMain.size = Size(450, 380);
    frmMain.formBorderStyle = FormBorderStyle.FIXED_SINGLE;

    txtPath = new TextBox;
    txtPath.size = Size(400, 20);
    txtPath.text = defaultPath;
    txtPath.top = 15;
    txtPath.left = 15;
    txtPath.parent = frmMain;    

    btnBrowse = new Button;
    btnBrowse.size = Size(80, 20);
    btnBrowse.text = "Browse...";
    btnBrowse.top = 35;
    btnBrowse.left = 15;
    btnBrowse.parent = frmMain;
    btnBrowse.click ~= &bntBrowse_onClick;
    
    lblInstruct = new Label;
    lblInstruct.size = Size(300, 20);
    lblInstruct.text = "Select parts to install: ";
    lblInstruct.top = 70; 
    lblInstruct.left = 15;
    lblInstruct.parent = frmMain;

    chk1 = new CheckBox;
    chk1.text = "Part 1";
    chk1.size = Size(100, 25);
    chk1.top = 85;
    chk1.left = 15;
    chk1.parent = frmMain;
    
    chk2 = new CheckBox;
    chk2.text = "Part 2";
    chk2.size = Size(100, 25);
    chk2.top = 110;
    chk2.left = 15;
    chk2.parent = frmMain;
    
    chk3 = new CheckBox;
    chk3.text = "Part 3";
    chk3.size = Size(100, 25);
    chk3.top = 135;
    chk3.left = 15;
    chk3.parent = frmMain;
    
    chk4 = new CheckBox;
    chk4.text = "Part 4";
    chk4.size = Size(100, 25);
    chk4.top = 160;
    chk4.left = 15;
    chk4.parent = frmMain;
    
    chk5 = new CheckBox;
    chk5.text = "Part 5";
    chk5.size = Size(100, 25);
    chk5.top = 185;
    chk5.left = 15;
    chk5.parent = frmMain;
    
    chk6 = new CheckBox;
    chk6.text = "Part 6";
    chk6.size = Size(100, 25);
    chk6.top = 210;
    chk6.left = 15;
    chk6.parent = frmMain;
    
    chk7 = new CheckBox;
    chk7.text = "Part 7";
    chk7.size = Size(100, 25);
    chk7.top = 235;
    chk7.left = 15;
    chk7.parent = frmMain;
    
    chk8 = new CheckBox;
    chk8.text = "Part 8";
    chk8.size = Size(100, 25);
    chk8.top = 260;
    chk8.left = 15;
    chk8.parent = frmMain;

    btnCheckAll = new Button;    
    btnCheckAll.text = "Check All";
    btnCheckAll.size = Size(100, 25);
    btnCheckAll.top = 230;
    btnCheckAll.left = 200;
    btnCheckAll.parent = frmMain;
    btnCheckAll.click ~= &bntCheckAll_onClick;
    
    btnCheckNone = new Button;
    btnCheckNone.text = "Uncheck All";
    btnCheckNone.size = Size(100, 25);
    btnCheckNone.top = 260;
    btnCheckNone.left = 200;
    btnCheckNone.parent = frmMain;
    btnCheckNone.click ~= &bntCheckNone_onClick;
    
    btnInstall = new Button;
    btnInstall.text = "Install";
    btnInstall.size = Size(100, 25);
    btnInstall.top = 300;
    btnInstall.left = 15;
    btnInstall.parent = frmMain;
    btnInstall.click ~= &bntInstall_onClick;

    Application.run(frmMain);
    
    return 0;


}

Controls

DescriptionShows how to create various controls using the DFL GUI library for Windows.
Date/TimeThu Dec 16, 2004 6:24 pm
Posted byjcc7

This program requires Vathix's DFL. I've tested it with DFL 0.4 and DMD 0.104.

Batch file:

@echo off
dmd controls.d -L/exet:nt/su:windows:4.0 ..\dfl.lib -I..
controls.exe
pause
import dfl.all;


int main()
{
    Form myForm;
    Label myLabel;
    Button myButton, btnExit;
    TextBox myTextBox;
    CheckBox myChkBox;


    void fileExitClick(Object sender, EventArgs ea)
    {
        Application.exitThread();
    }
        
        
    void myButtonClick(Object sender, EventArgs ea)
    {
        MessageBox.show("Congratulations! You clicked the Button.", "My Example Program");
    }
        

    myForm = new Form;
    myForm.text = "DFL Example";
    
    myButton = new Button;
    myButton.text = "Button";
    myButton.size = Size(100, 25);
    myButton.parent = myForm;    
    myButton.click ~= &myButtonClick;

    myTextBox = new TextBox;
    myTextBox.text = "TextBox";
    myTextBox.size = Size(100, 25);
    myTextBox.left = 150;
    myTextBox.parent = myForm;
        
    myLabel = new Label;
    myLabel.text = "Label";
    myLabel.size = Size(100, 14);
    myLabel.top = 50;
    myLabel.parent = myForm;
        
    myChkBox = new CheckBox;
    myChkBox.text = "CheckBox";
    myChkBox.size = Size(100, 20);
    myChkBox.top = 80;
    myChkBox.parent = myForm;

    btnExit = new Button;
    btnExit.text = "Exit";
    btnExit.top = 150;
    btnExit.size = Size(100, 25);
    btnExit.parent = myForm;    
    btnExit.click ~= &fileExitClick;    

    Application.run(myForm);
    
    return 0;


}

Mango

I/O with Mango

DescriptionShows you how to use the Mango library for I/O.
Date/TimeFri Aug 20, 2004 3:13 am
Posted byAnonymous
import mango.io.stdio;

int main()
{
    Stdout << "MANGO I/O EXAMPLE 1\n\n";
    
    char[] name;

    Stdout << "NAME: ";
    Stdin >> name;

    Stdout << "\n\nHello, " << name << ", how are you?\n";

    return 0;


}

Standard Library

String usage: split and splitlines

DescriptionExercises std.string.splitlines and std.string.split. (Note: has simulatedFile to be 'self-contained'. Use commented out lines for real file, assumed to be named tutorial.d)
Date/TimeFri Sep 24, 2004 3:15 pm
Posted byLynn
import std.stdio;
import std.string;

//import std.file;

//char[] actualFile = cast(char[])std.file.read("tutorial.d");

const char[] simulatedFile = 
  "Line 1 one\n"
  "Line 2 two\n"
  "Line 3 three";

void main ()
{
  char[][] allLines = splitlines(simulatedFile);

  foreach (char[] curLine; allLines) {
    writef(curLine, " = ");
    char[][] allWordsInCurLine = split(curLine);
    foreach (char[] curWord; allWordsInCurLine) {
      writef('[', curWord, ']', ' ');
    }
    writefln();
  }
}

I/O on stdin and stdout streams

Description A very simple example of I/O on stdin and stdout.
Date/TimeSun May 16, 2004 9:20 am
Posted byegon
/* A very simple example of I/O on stdin and stdout.
 * It uses streams instead of stc.c.stdio calls.
 */

import std.stream;
import std.string;

int main()
{
    char[] input;
    char[] output;

    // Ask for a string

    std.stream.stdout.writeLine("Converts a lowercase string to uppercase.");
    std.stream.stdout.writeLine("Please enter a string:");
    input = std.stream.stdin.readLine();

    // Convert to upper and print it
    output = input.toupper();
    std.stream.stdout.writeLine(output);

    return 0;

}

httpHEAD

DescriptionDemonstrates Socket and SocketStream.
Date/TimeSat May 29, 2004 5:20 pm
Posted byAnonymous
/*
 * Title: httpHEAD
 * Author: michal wallace (http://withoutane.com/)
 * License: public domain
 * Purpose: demonstrate sockets in D
 *
 * This program makes  an HTTP HEAD
 * request to a server specified on the
 * command line and prints the response.
 *
 */

private import std.socket;
private import std.socketstream;
private import std.string;


const int WEBPORT=80;

void main(char[][] args){ 

  if (args.length != 3) {
    printf("usage: httpHEAD host path");
    return(1);
  }

  char[] host = args[1];
  char[] path = args[2];

  // open a socket:

  InternetHost ih = new InternetHost;
  ih.getHostByName(host);
  InternetAddress ia = new InternetAddress(ih.addrList[0], WEBPORT);
  TcpSocket sock = new TcpSocket();
  sock.connect(ia);

  // send the HTTP request
  sock.send("HEAD " ~ path ~ " HTTP/1.0\n\n");
        
  // read and print the result:

  char[] line;
  SocketStream stream = new SocketStream(sock);
  while (! stream.eof()) {
    line = stream.readLine();
    if (line=="") break;
    printf ("%s\n", toStringz(line));
  }
}

OutBuffer

DescriptionBasic use of std.outbuffer.OutBuffer Outbuffer avoids reallocation of buffers when the '~' operator is used, and thus should give better performance.
Date/TimeFri Sep 24, 2004 8:43 am
Posted byLynn
import std.outbuffer;
import std.string;
import std.stdio;

void main ()
{
  int areaCode = 800, lata = 555, lastPart = 1212;

  std.outbuffer.OutBuffer buf = new OutBuffer;
  buf.write("Test of building phone number: ");
  buf.write('(');
  buf.write(toString(areaCode));
  buf.write(") ");
  buf.write(toString(lata));
  buf.write("-");
  buf.write(toString(lastPart));
  writefln("buf: ", buf.toString());


// instead of:
  writefln("buf: Test of building phone number: (" 
      ~ toString(areaCode) ~ ") " 
      ~ toString(lata) ~ "-" 
      ~ toString(lastPart));
}

Win32 Registry api

DescriptionReads int and string from Notepad registry entries. Creates, writes, and reads int and string registry entries for dsource app.
Date/TimeTue Sep 28, 2004 9:20 pm
Posted byAnonymous
/*
 *  Copyright (C) 2004 by Digital Mars, www.digitalmars.com
 *  Written by Lynn Allan by adapting code by Walter Bright
 *
 *  This software is provided 'as-is', without any express or implied
 *  warranty. In no event will the authors be held liable for any damages
 *  arising from the use of this software.
 *
 *  Permission is granted to anyone to use this software for any purpose,
 *  including commercial applications, and to alter it and redistribute it
 *  freely, subject to the following restrictions:
 *
 *  o  The origin of this software must not be misrepresented; you must not
 *     claim that you wrote the original software. If you use this software
 *     in a product, an acknowledgment in the product documentation would be
 *     appreciated but is not required.
 *  o  Altered source versions must be plainly marked as such, and must not
 *     be misrepresented as being the original software.
 *  o  This notice may not be removed or altered from any source
 *     distribution.
 */

/* Compile with:
 * dmd test.d advapi32.lib 
 */

import std.stdio;
import std.string;
import std.c.windows.windows;

extern (Windows)   // Not defined in windows.d

{
LONG RegQueryValueExA(HKEY hkey, 
                      LPCTSTR keyName, 
                      LPDWORD reservedNull,
                      LPDWORD type, 
                      void*   data,
                      LPDWORD len);
}

void main ()
{
  ReadNotepadKeys();
  WriteAppKeys();
}

void ReadNotepadKeys()
{
  HKEY hkey;
  LONG result;
  DWORD dwType;
  const int BUF_SZ = 40;
  DWORD dwLen = BUF_SZ;
  char[BUF_SZ] regBuf;
  int weight;

  result = RegOpenKeyA(HKEY_CURRENT_USER, 
                       "Software\\Microsoft\\Notepad", &hkey);
  writefln("OpenKey Result: ", result);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  result = RegQueryValueExA(hkey, 
                            cast(char*)"lfFaceName", 
                            null, 
                            &dwType, 
                            cast(void*)regBuf, 
                            &dwLen);
  writefln("Query String Result: ", result, "  Len: ", dwLen);
  assert(result == ERROR_SUCCESS);
  writefln("RegBuf: [", regBuf[0..dwLen-1], "]");

  dwLen = 4;
  result = RegQueryValueExA(hkey, 
                            cast(char*)"lfWeight", 
                            null, 
                            &dwType, 
                            cast(void*)&weight, 
                            &dwLen);
  writefln("Query DWORD Result: ", result, "  Weight: [", weight, "]");
  assert(result == ERROR_SUCCESS);

  result = RegCloseKey(hkey);
  writefln("CloseKey Result: ", result);
  assert(result == ERROR_SUCCESS);
}


void WriteAppKeys()
{
  HKEY hkey;
  LONG result;
  DWORD dwType;
  const int BUF_SZ = 4;
  DWORD dwLen = BUF_SZ;
  char[BUF_SZ] regBuf;
  DWORD displosition;
  int param = 0x1001;

  result = RegCreateKeyExA(HKEY_CURRENT_USER, 
                           "Software\\dsource\\Test\\Settings", 
                           cast(uint)null,
                           null,
                           REG_OPTION_NON_VOLATILE,
                           KEY_ALL_ACCESS,
                           null,
                           &hkey,
                           &displosition);
  writefln("CreateKey Result: ", result);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  dwLen = 4;
  result = RegSetValueExA(hkey, 
                          cast(char*)"Param", 
                          0, 

                          REG_DWORD, 
                          cast(BYTE*)&param, 
                          dwLen);
  writefln("Set DWORD Result: ", result);
  assert(result == ERROR_SUCCESS);

  char[] regGreeting = "Hello and Goodbye";
  result = RegSetValueExA(hkey, 
                          cast(char*)"Greeting", 
                          0, 

                          REG_SZ, 
                          cast(BYTE*)toStringz(regGreeting), 
                          regGreeting.length);
  writefln("Set DWORD Result: ", result);
  assert(result == ERROR_SUCCESS);

  result = RegCloseKey(hkey);
  writefln("CloseKey Result: ", result);
  assert(result == ERROR_SUCCESS);

  result = RegOpenKeyA(HKEY_CURRENT_USER, 
                       "Software\\dsource\\Test\\Settings", &hkey);
  writefln("OpenKey Result: ", result);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  dwLen = 4;
  int check;
  result = RegQueryValueExA(hkey, 
                            cast(char*)"Param", 
                            null, 
                            &dwType, 
                            cast(void*)&check, 
                            &dwLen); 
  writefln("Query DWORD Result: ", result, "  Check: [", check, "]");
  assert(result == ERROR_SUCCESS);
  assert(check == param);

  result = RegCloseKey(hkey);
  writefln("CloseKey Result: ", result);
  assert(result == ERROR_SUCCESS);
}

Using the File's "FileMode" attribute

DescriptionUsing std.stream methods to create, read from, write to, append to, and delete a file.
Date/TimeSat Feb 5, 2005 5:47 pm
Posted bySpottedTiger
// streamtest.d
private import std.stream; 
private import std.stdio; 

void main() 
{ 
   // FileMode.In     - Read In 

   // FileMode.Out    - Write To 
   // FileMode.OutNew - Create \ Empty Existing 
   // FileMode.Append - Write Appending Data 
   File f = new File( r"C:\blargh.txt", FileMode.OutNew ); 
   char[] sLine1; 
   char[] sLine2; 
    
   // Creates a file or 

   // Empty the exists file 
   //f.create( r"C:\blargh.txt" ); // same as the .OutNew above 
   f.writeLine( "Bleagh!" ); 
   f.close(); 
    
   // Opens and read from the file 
   f.open( r"C:\blargh.txt", FileMode.In ); 
   sLine1 = f.readLine(); 
   f.close(); 
    
   writefln( "1st.sLine1=\"%s\"", sLine1 ); 
    
   // Append new data to the end of the file 

   f.open( r"C:\blargh.txt", FileMode.Append ); 
   f.writeLine( "Bleagh2!" ); 
   f.close(); 
  
   f.open( r"C:\blargh.txt", FileMode.In ); 
   sLine1 = f.readLine(); 
   sLine2 = f.readLine(); 
   f.close(); 
    
   writefln( "2nd.sLine1=\"%s\"", sLine1 ); 
   writefln( "2nd.sLine2=\"%s\"", sLine2 ); 
  
   // Deletes the file 
   f.remove( r"C:\blargh.txt" ); 
} 

Output: 
C:\dmd>bin\dmd streamtest.d 
C:\dmd\bin\..\..\dm\bin\link.exe streamtest,,,user32+kernel32/noi; 

C:\dmd>streamtest 

1st.sLine1="Bleagh!" 
2nd.sLine1="Bleagh!" 
2nd.sLine2="Bleagh2!" 

C:\dmd>

Elapsed Time (uses std.date and std.c.time)

DescriptionCalculate elapsed time using std.date and std.c.time functions
Date/TimeWed Dec 15, 2004 2:31 pm
Posted byjcc7
import std.stdio;
import std.date;
import std.c.time;

void main ()
{
  const int DelayMillis = 2000;
  printf("Test will run for about %d millis\n", DelayMillis);

  d_time startTime = std.date.getUTCtime();
  d_time curTime = startTime;
  d_time elapsed = 0;



  // Code to be timed goes here ... just spin with msleep
  while(elapsed < DelayMillis) {
    curTime = getUTCtime();
    elapsed = curTime - startTime;
    std.c.time.msleep(100);
  }
  printf("Ticks/Sec: %u\n", std.date.TicksPerSecond);
  printf("Start: %u\n", startTime);
  printf("Current: %u\n", curTime);
  printf("Elapsed: %u\n", elapsed);

  return 0;


}

Contributed by Lynn


Base64 Decoding

DescriptionShows how to convert base64 text file into a binary file.
Date/TimeWed Dec 15, 2004 2:30 pm
Posted byjcc7
/*

File:   b64_to_bin.d
Author: J C Calvarese (http://jcc_7.tripod.com/d/)
Date:   2004-01-22

*/ 

Purpose:

Converts base64 encoded files found at the web interface to the D newsgroup into binary files. (I tested it with post D:22264)

Instructions:

Save the page that includes the base64 encoding as something like "wwwwnews.html". Call this program as "b64_to_bin.exe wwwnews.html". Rename "wwwnews.html.bin" to whatever the file name should be.

Limitations:

This routine only captures the first file if more than one is attached.

import std.base64;
import std.c.stdio;
import std.string;
import std.stream;

void main(char[][] args)
{

    if (args.length > 1)
    {
        File b64_file = new File(args[1]);
        char[] line_in;
        printf("Processing (%.*s)...\n", args[1]);
        while (!b64_file.eof())
        {
            line_in = b64_file.readLine();
            if (tolower(line_in) == "content-transfer-encoding: base64<br>")
            {
                char[] content;

                printf("Base64 content found...\n");
                line_in = b64_file.readLine();
                line_in = b64_file.readLine();
                line_in = b64_file.readLine();
    
                line_in = line_in[9..line_in.length];            
                while(line_in != "</pre>")
                {
                    content ~= line_in;
                    line_in = b64_file.readLine();
                }

                char[] decoded_content = decode(content);

                File output = new File();
                output.create(args[1] ~ ".bin", FileMode.Out);
                output.writeBlock(decoded_content, decoded_content.length);
                output.close();
                printf("File saved as %.*s.bin\n\n", args[1]);
            }
        }
            
    }
    else

        printf("\nb64_to_bin:\nUsage: b64_to_bin [filename to process]\n\n");
}

Compile all files into a .lib

DescriptionThis code will create a batch file that will compile files in the current directory into a .lib (designed for Windows).
Date/TimeWed Dec 15, 2004 2:30 pm
Posted byjcc7
/* 

Compile All (compall.d)
Author:  J C Calvarese 
License: Public Domain

With a little effort, it might run on Linux, but I don't currently 
have a Linux machine to try it.

Compiling instructions:

dmd compall.d -unittest
compall.exe
pause


*/

import std.recls; /* for Search */

import std.stream; /* for File */
import std.string; /* for replace */
import std.file; /* for getcwd */


unittest /* requires importation of std.recls and std.file */
{    
    /* Test the current directory from std.recls against std.file's getcwd. */
    
    Search  searchBase  =   new Search(".", ".", RECLS_FLAG.RECLS_F_DIRECTORIES);
    foreach(Entry entry; searchBase)
    {
        /* I'm only expecting one entry, but I don't know a way to access it without a foreach. */

        assert(entry.DirectoryPath() == getcwd ~ "\\");    
    }
    assert(getcwd != "");
    printf("Unittests successful.\n");    
}


void main()
{   
    /* Recursively adds each of the files in the current directory to a batch 
    file as a compile command and creates a .lib. */

    char[] bufCompile;
    char[] bufLib;
    char[] relPath;
    char[] libName;
    
    /* TODO: command line argument to allow adjusting this. */
    char[] curPath = getcwd;

    /* TODO: command line argument to allow adjusting this. */
    char[] DirBase = curPath ~ "\\";
        
    /* TODO: command line argument to allow adjusting this. */

    char[] includePath = "-I.."; 
    
    int i = rfind(curPath, "\\");
    if(i>-1)
        libName = curPath[i + 1 .. curPath.length];
    else

        libName = "mylib";

    bufLib = "lib -c " ~ libName ~ ".lib";


    Search  search  =   new Search(".", "*.d", RECLS_FLAG.RECLS_F_RECURSIVE);
    foreach(Entry entry; search)
    {        
        with(entry)
        { 
            relPath = DirectoryPath();
            
            /* Make the path relative */

            relPath = replace(relPath, DirBase, "");
            bufCompile ~= "dmd -c " ~ relPath ~ File() ~ " " ~ includePath ~ \r\n;
                        
            /* Change the extention form ".d" to ".obj" and add to the lib command. */
            bufLib ~= " " ~ replace(File(), ".d", ".obj");
        }
    }
    bufLib ~= \r\n;
    printf("%.*s", bufCompile ~ bufLib);

    File f = new File();
    with(f)
    {
        f.create("makelib.bat");
        f.writeString(bufCompile ~ bufLib ~ "pause\r\nerase *.obj\r\n");
        f.close();    
    }
}

writef

DescriptionSince DMD 0.95, writef is available as a replacement for printf. (Access Violations can become a thing of the past.)
Date/TimeWed Dec 15, 2004 2:31 pm
Posted byjcc7

Find more details in the official docs.

import std.stdio;

void main()
{
    /* Integers */
    
    int i=123;

    writef(i, \n);         /* prints "123" */

    writef("%s", i, \n);   /* prints "123" */
    writef(\n);
    
    writef("Leading zeros\n");
    
    /* prints "123" (would have a leading zero or zeros if necessary) */
    writef("%02s", i, \n); 

    /* prints "123" (would have a leading zero or zeros if necessary) */

    writef("%03s", i, \n); 

    /* prints "0123" (leading zero) */
    writef("%04s", i, \n); 

    /* prints "00123" (leading zeros) */
    writef("%05s", i, \n); 


    /* Reals */

    real x = 1.0;
    writef(x, \n);
    writef("%f", x, \n);

    /* from digitalmars.D.bugs:894 */
    printf( "%Lf\n", x ); 



    x = 2.345;
    writef(x, \n);
    writef("%f", x, \n);

    /* from digitalmars.D.bugs:894 */

    printf( "%Lf\n", x ); 
}

std.perf

DescriptionUse the HighPerformanceCounter object in std.perf to find out how long it takes to execute some code.
Date/TimeWed Dec 15, 2004 2:31 pm
Posted byjcc7
import std.stdio;
import std.c.time;
import std.perf;


void main ()
{
  HighPerformanceCounter hpc = new HighPerformanceCounter();
  hpc.start();

  /* Code to be timed goes here ... just msleep for 1.2 seconds */
  std.c.time.msleep(1200);

  hpc.stop();
  writefln("hpc ms: ", hpc.microseconds(),
              "  Seconds: ", hpc.microseconds() / 1000000.0);
}

Contributed by Lynn in the forum.


Make all.html

DescriptionCreates an HTML file that lists all of the other files in the directory.
Date/TimeWed Dec 15, 2004 2:32 pm
Posted byjcc7
/* 

File:       make_all_html.d
Author:     J C Calvarese
License:    Public Domain
Date:       2004-10-27
Purpose:    Creates an HTML file that lists all of 
            the other files in the directory.

*/

import std.recls;
import std.file;



void main()
{   
    Search  search  =   new Search(getcwd(), "*.html", RECLS_FLAG.RECLS_F_FILES);
    printf(`<html>` ~ "\n" ~ 
      `<body>` ~ "\n" ~ 
      `<head>` ~ "\n" ~ 
      `<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">` ~ "\n" ~ 
      `<title>All Topics</title>` ~ "\n" ~ 
      `<link rel="stylesheet" type="text/css" href="style.css" >` ~ "\n" ~ 
      `</head>` ~ "\n" ~ 
      `<body>` ~ "\n" ~ 
      `<h1>All Files</h1><ul>`);

    foreach(Entry entry; search)
    {
        with(entry)
        { 
            if(File() != "all.html")
                printf(`<li><a href="%.*s">%.*s</a></li>` ~ "\n", File(), File());
        }
    }
    printf("</ul>\n</body>\n</html>");
}

Sample Batch File:

@echo off
dmd make_all_html.d
make_all_html.exe > all.html
pause

File Input

DescriptionRead in data from a file.
Date/TimeFri May 14, 2004 10:52 pm
Posted byjcc7
/* 

File:      file_io.d
Author:    Justin C. Calvarese, http://jcc_7.tripod.com/d/
License:   Public Domain

Purpose:   Demonstrates getting input from a text file.
*/ 

Find out more about std.stream in the D Specification.

import std.stream;

int main(char[][] args)
{
    char[] c;
    char[] fn;
    

    File f = new File("file_io.html");
    while (!f.eof())
    {
        c = f.readLine();
        printf("%.*s\n", c);
    }
    
    f.close();    

    return 0;



}

recls

DescriptionRecursive directory analysis
Date/TimeFri May 14, 2004 10:51 pm
Posted byjcc7

In the future (or maybe in the present now - I haven't checked recently), recls will be compiled directly into the D runtime library. As of this writing (DMD 0.79), the recls library has to be made and "recls.lib" must included in the commands sent to the linker by the compiler.

  1. Make recls.lib using a command line like this... D:\DMD\SRC\PHOBOS\ETC\C\RECLS>make -fwin32.mak
  2. Then put recls.lib in the a lib path (probably either \dm\lib or \dmd\lib).

Here's the batch file I used to compile and test my recls sample:

@echo off
dmd recls.d recls.lib
pause
cd \
\pgm\d\testing\phobos\recls.exe
pause

You might also want to read the recls FAQ.

/* 

File:       recls.d
Author:     J C Calvarese
License:    Public Domain
Date:       2004-01-23
Purpose:    Demonstrate the fundamentals of using the recls library in D.

*/

import std.recls;

void main()
{   
    Search  search  =   new Search(".", "*.*", RECLS_FLAG.RECLS_F_RECURSIVE);
    foreach(Entry entry; search)
    {
        with(entry)
        { 
            if(!ShortFile())
                printf("%.*s%.*s\n", DirectoryPath(), File());
            else

                printf("%.*s%.*s (%.*s)\n", DirectoryPath(), File(), ShortFile());
        }
    }
}

Regular Expressions

DescriptionDemonstrates some simple uses of regular expressions. These examples are a little contrived as it'd actually be easier to use std.string to do these tests.
Date/TimeFri May 14, 2004 10:52 pm
Posted byjcc7
import std.regexp;
import std.c.stdio;

bit isalpha(char[] c)
{
    RegExp myRegExp;    
    myRegExp = new RegExp("^[a-zA-Z_]+$", "");    
    return cast(bit) myRegExp.test(c);
}



bit isspace(char[] c)
{
     /* true if c is whitespace, false otherwise */

    RegExp myRegExp = new RegExp("^\\s+$", "");
    return cast(bit) myRegExp.test(c); 
}




bit isdigit(char[] c)
/* true if c is a decimal digit, false otherwise */
{
    RegExp myRegExp = new RegExp("^\\d+$", "");
    return cast(bit) myRegExp.test(c);
}


bit ishexdigit(char[] c)
/* true if c is a hexadecimal digit, false otherwise */
{
    RegExp myRegExp = new RegExp("^[0-9A-F]+$", "");
    /* If it were D code, "_" would also be valid */

    return cast(bit) myRegExp.test(c);
}

bit isoctdigit(char[] c)
/* true if c is an octal digit, false otherwise */
{
    RegExp myRegExp = new RegExp("^[0-7]+$", "");
    return cast(bit) myRegExp.test(c);
}



bit issymbol(char[] c)
/* true if c is legal SQL symbol, false otherwise */
{    
    RegExp myRegExp = new RegExp("^[\\(\\)\\[\\]\\.,;=<>\\+\\-\\*/&\\^]+$", "");
    return cast(bit) myRegExp.test(c);
}



unittest
{
    /* compile with the -unittest flag to run these tests */

    printf("Testing functions...\n");
    
    assert(isalpha("a") && isalpha("A") && !isalpha("9") && isalpha("_") && isalpha("R") && !isalpha("&"));
    
    assert(issymbol("(") && issymbol(")") && issymbol("[") && issymbol("]") && issymbol(")") && 
      issymbol("[") && issymbol("]") && issymbol("-") && issymbol("/") && issymbol("=") && issymbol("*") && 
      issymbol(".") && !issymbol("a") && !issymbol("0") && !issymbol("Y") && !issymbol("\\"));
        
    assert(isdigit("0") && isdigit("7") && isdigit("9") && !isdigit("A")  && !isdigit("^") && !isdigit("G"));

    assert(ishexdigit("0") && ishexdigit("7") && ishexdigit("A")  && !ishexdigit("^") && !ishexdigit("G"));

    assert(isoctdigit("0") && isoctdigit("7") && !isoctdigit("8")  && !isoctdigit("A")  && !isoctdigit("^"));

    assert(isspace(" ")  && isspace("\t") && !isspace("o")  && !isspace(".")  && !isspace("5"));

    printf("Functions tested successfully.\n");
}


void main()
{

    /* Compile with the -debug flag for this statement to run. */

    debug printf("Main Program.\n");
}

std.stream readLine

DescriptionRead a file line-by-line.
Date/TimeWed Jun 23, 2004 11:24 pm
Posted byjcc7
Based on code from D.bugs:221
import std.c.stdio;

import std.stream;

int main (char [] [] args )
{
 File file = new File("testreadLine.d");

 char[] line;

 do

 {
  line = file.readLine();
  printf("Line: %.*s\n",line);
 }while(!file.eof);


 getch();
 return 1;
}

Threads

DescriptionDemonstrates the use of std.thread with two threads.
Date/TimeFri May 14, 2004 10:51 pm
Posted byjcc7
/*

Title:    Threads

Author:   J C Calvarese, http://jcc_7.tripod.com/d/
License:  Public domain
Purpose:  To demonstrate the use of std.thread.


You'll need to adjust these two paths to fit your own computer: 

*/

char[] path1 = "c:\\windows\\fonts"; 
char[] path2 = "c:\\windows\\temp"; 


import std.recls;
import std.thread;


int run1(void *ptr)
{
    printf("Thread 1 started...\n");
    Search  search  =   new Search(path1, "*.*", RECLS_FLAG.RECLS_F_RECURSIVE);
    foreach(Entry entry; search)
    {
        with(entry)
        { 
            if(!ShortFile())
                printf("T1: %.*s%.*s\n", DirectoryPath(), File());
            else

                printf("T1: %.*s%.*s (%.*s)\n", DirectoryPath(), File(), ShortFile());
        }
    }     
    printf("Thread 1 finished.\n"); 
    return 0;


}

int run2(void *ptr)
{
    printf("Thread 2 started...\n");    
    Search  search  =   new Search(path2, "*.*", RECLS_FLAG.RECLS_F_RECURSIVE);
    foreach(Entry entry; search)
    {
        with(entry)
        { 
            if(!ShortFile())
                printf("T2: %.*s%.*s\n", DirectoryPath(), File());
            else

                printf("T2: %.*s%.*s (%.*s)\n", DirectoryPath(), File(), ShortFile());
        }
    }     
    printf("Thread 2 finished.\n"); 
    return 0;


}

void main()
{   
    Thread t1 = new Thread(&run1, null);
    
    Thread t2 = new Thread(&run2, null);
    
    
    t1.start();
    t2.start();
    
    while(t1.getState() == std.thread.Thread.TS.RUNNING)
        Thread.yield ();    
}

You may need to make the recls.lib as explained here.

Compile instructions:
@echo off
dmd threads.d recls.lib
pause
threads.exe
pause

Thanks to Burton Radons for his helpful posts on this topic (D:10231 and D:10236).


Variadic Functions

Descriptionshows typesafe variadic functions (requires DMD 0.93+)
Date/TimeWed Jun 23, 2004 11:23 pm
Posted byjcc7

Pieced together from examples in the D Specification.

This functionality was introduced in DMD 0.93.

/* To protect against the vagaries of stack layouts on different CPU architectures, 
use std.stdarg to access the variadic arguments: */

import std.stdarg; 

class FOO{}

void foo(...)
{
    printf("%d arguments\n", _arguments.length);
    for (int i = 0; i < _arguments.length; i++)
    {   _arguments[i].print();

    if (_arguments[i] == typeid(int))
    {
        int j = va_arg!(int)(_argptr);
        printf("\t%d\n", j);
    }
    else if (_arguments[i] == typeid(long))
    {
        long j = va_arg!(long)(_argptr);
        printf("\t%lld\n", j);
    }
    else if (_arguments[i] == typeid(double))
    {
        double d = va_arg!(double)(_argptr);
        printf("\t%g\n", d);
    }
    else if (_arguments[i] == typeid(FOO))
    {
        FOO f = va_arg!(FOO)(_argptr);
        printf("\t%p\n", f);
    }
    else

        assert(0);
    }
}



void main()
{
    FOO f = new FOO();

    printf("%p\n", f);
    foo(1, 2, 3L, 4.5, f);
}
    



/*
which prints:

    00870FD0
    5 arguments
    int
        1
    int
        2
    long
        3
    double
        4.5
    FOO
        00870FD0
*/ 

Variable Arguments

DescriptionUse std.c.stdarg for variable arguments
Date/TimeWed Jun 23, 2004 11:20 pm
Posted byjcc7

The std.c.stdarg module is now obsolete with the release of DMD 0.93 (use std.stdarg instead).

import std.c.stdarg;


int foo(char *x, ...)
{
    va_list ap;

    va_start!(typeof(x))(ap, x);
    printf("&x = %p, ap = %p\n", &x, ap);

    int i;
    i = va_arg!(typeof(i))(ap);
    printf("i = %d\n", i);

    long l;
    l = va_arg!(typeof(l))(ap);
    printf("l = %lld\n", l);

    uint k;
    k = va_arg!(typeof(k))(ap);
    printf("k = %u\n", k);

    va_end(ap);

    return i + l + k;
}


void main()
{
    int j;

    j = foo("hello", 3, 23L, 4);
    printf("j = %d\n", j);
    assert(j == 30);
}


/*
adapted from http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/273
*/ 

zip

DescriptionUsing the zip compression format in D.
Date/TimeFri Sep 24, 2004 11:18 pm
Posted byjcc7

D has support for the zip compression format in std.zip. This example demonstrates its use. You'll need an archive called "test.zip". You can download a zip file that I've used: [ look for test.zip on this page ]

Posted by Walter at D:20379.

import std.file;
import std.date;
import std.zip;
import std.zlib;


int main(char[][] args)
{
    byte[] buffer;
    std.zip.ZipArchive zr;
    char[] zipname;
    ubyte[] data;

    testzlib();
    if (args.length > 1) zipname = args[1];
    else zipname = "test.zip";
    buffer = cast(byte[])std.file.read(zipname);
    zr = new std.zip.ZipArchive(cast(void[])buffer);
    printf("comment = '%.*s'\n", zr.comment);
    zr.print();

    foreach (ArchiveMember de; zr.directory)
    {
         de.print();
         printf("date = '%.*s'\n", std.date.toString(std.date.toDtime(de.time)));
        
         arrayPrint(de.compressedData);
        
         data = zr.expand(de);
         printf("data = '%.*s'\n", data);
    }

    printf("**Success**\n");

    zr = new std.zip.ZipArchive();
    ArchiveMember am = new ArchiveMember();
    am.compressionMethod = 8;
    am.name = "foo.bar";
    //am.extra = cast(ubyte[])"ExTrA";

    am.expandedData = cast(ubyte[])"We all live in a yellow submarine, a yellow submarine";
    am.expandedSize = am.expandedData.length;
    zr.addMember(am);
    void[] data2 = zr.build();
    std.file.write("foo.zip", cast(byte[])data2);

    return 0;



}

void arrayPrint(ubyte[] array)
{
    //printf("array %p,%d\n", (void*)array, array.length);

    for (int i = 0; i < array.length; i++)
    {
        printf("%02x ", array[i]);
        if (((i + 1) & 15) == 0)



         printf("\n");
    }
    printf("\n\n");
}

void testzlib()
{
    ubyte[] src = cast(ubyte[])

"the quick brown fox jumps over the lazy dog\r
the quick brown fox jumps over the lazy dog\r
";
    ubyte[] dst;

    arrayPrint(src);
    dst = cast(ubyte[])std.zlib.compress(cast(void[])src);
    arrayPrint(dst);
    src = cast(ubyte[])std.zlib.uncompress(cast(void[])dst);
    arrayPrint(src);
}

Zlib

Descriptiona simplified version of the zip example that Walter B. posted. It only has zlib's compress and uncompress calls to minimize 'distractions' from using zlib.
Date/TimeFri Aug 27, 2004 9:36 am
Posted byjcc7
import std.zlib; 

int main(char[][] args)
{
    ubyte[] beforeCompression = cast(ubyte[])
"the quick brown fox jumps over the lazy dog\r
the quick brown fox jumps over the lazy dog\r
";
    ubyte[] compressed;
    ubyte[] afterDecompression;

    compressed = cast(ubyte[])std.zlib.compress(cast(void[])beforeCompression);
    afterDecompression = cast(ubyte[])std.zlib.uncompress(cast(void[])compressed);

    assert(beforeCompression == afterDecompression);
    printf("Success! Uncompressed Size: %d Compressed Size: %d\n",
      beforeCompression.length, compressed.length);

    return 0;


}

Contributed by Lynn


Unzip using std.zip

DescriptionShows how to extract a file from a .zip archive.
Date/TimeFri Sep 24, 2004 11:22 pm
Posted byjcc7

Shows how to extract a file from a .zip archive. Adapted from Walter's zlib example by jcc7.

You'll need an archive called "test.zip". You can download a zip file that I've used: [ look for test.zip on this page ]

import std.file;
import std.date;

import std.stream;
import std.zip;
import std.zlib;


int main(char[][] args)
{
    File f;
    byte[] buffer;
    std.zip.ZipArchive zr;
    char[] zipname;


    if (args.length > 1) zipname = args[1];
    else zipname = "test.zip";

    buffer = cast(byte[])std.file.read(zipname);
    zr = new std.zip.ZipArchive(cast(void[])buffer);

    foreach (ArchiveMember de; zr.directory)
    {
        f = new File(de.name, FileMode.Out);

        zr.expand(de);
        f.write(de.expandedData);
    }

    printf("Success!\n");

    return 0;


}

Windows GUI

MiniCalc

DescriptionSimple Windows GUI example with additional functionality beyond winsamp.d and winsamp2.d provided with dmd.zip. Uses Win32 api (no gui framework) with several TextEdit controls.
Date/TimeSat Sep 25, 2004 8:58 am
Posted byLynn
/* Compile with:
 *  dmd MiniCalc gdi32.lib MiniCalc.def
 */

import std.string;
import std.c.windows.windows;


const int IDC_BTN_PLUS = 103;
const int IDC_BTN_MINUS = 104;
const int IDC_EDIT_FIRST_NUMBER = 105;

const int IDC_EDIT_SECOND_NUMBER = 106;
const int IDC_EDIT_RESULT_NUMBER = 107;

static HINSTANCE ghInstance;

static HWND      ghPlusBtn;
static HWND      ghMinusBtn;
static HWND      ghFirstNumberEdit;
static HWND      ghSecondNumberEdit;
static HWND      ghResultNumberEdit;
static HWND      ghWndMain;


void CreateControls()
{
  HWND hChapSelectorTree;
  
  ghPlusBtn = CreateWindowA("BUTTON", "Plus", 
                 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                 5, 5, 53, 25, ghWndMain, cast(HMENU) IDC_BTN_PLUS, 
                 ghInstance, null);

  ghMinusBtn = CreateWindowA("BUTTON", "Minus", 
                 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                 60, 5, 53, 25, ghWndMain, 
                 cast(HMENU) IDC_BTN_MINUS, 
                 ghInstance, null);

  ghFirstNumberEdit = CreateWindowA("EDIT", "0", 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 32, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_FIRST_NUMBER, ghInstance, null);

  ghSecondNumberEdit = CreateWindowA("EDIT", "20", 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 60, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_SECOND_NUMBER, ghInstance, null);
  
  ghResultNumberEdit = CreateWindowA("EDIT", "", 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 87, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_RESULT_NUMBER, 
                 ghInstance, null);
}


void DoMessagePump()
{
  MSG msg;
  while (GetMessageA(&msg, cast(HWND) null, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessageA(&msg);
  }
}


void CreateMainWindow()
{
  HWND hWnd;
  hWnd = CreateWindowA("DWndClass", 
               "MiniCalc", 
               WS_THICKFRAME | WS_MAXIMIZEBOX 
               | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE,
               CW_USEDEFAULT, CW_USEDEFAULT, 
               125, 150, HWND_DESKTOP,
               cast(HMENU) null, ghInstance, null);
  assert(hWnd);
  ghWndMain = hWnd;
}


void InitApplication()
{
  WNDCLASS wc;
  wc.lpszClassName = "DWndClass";
  wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = &WindowProc;
  wc.hInstance = ghInstance;
  wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
  wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
  wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = null;
  wc.cbClsExtra = wc.cbWndExtra = 0;


  assert(RegisterClassA(&wc));
}

void InitInstance()
{
  ghInstance = GetModuleHandleA(null);
  InitApplication();

  CreateMainWindow();

  CreateControls();
}

/**********************************************************/

/* Note the similarity of this code to the console D startup
 * code in \dmd\src\phobos\dmain2.d
 * You'll also need a .def file with at least the following in it:
 *  EXETYPE NT
 *  SUBSYSTEM WINDOWS
 */

extern (C) void gc_init();

extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();

extern (C) void _moduleUnitTests();

extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
            LPSTR lpCmdLine, int nCmdShow)
{
  int result = 1;

  gc_init();      // initialize garbage collector

  _minit();     // initialize module constructor table

  try {
    _moduleCtor();    // call module constructors
    _moduleUnitTests(); // run unit tests (optional)

    InitInstance();
    DoMessagePump();
  }
  catch (Object o) {    // catch any uncaught exceptions

    MessageBoxA(null, cast(char *)o.toString(), "Error",
                MB_OK | MB_ICONEXCLAMATION);
    result = 0;   // failed
  }
  gc_term();      // run finalizers; terminate garbage collector

  return result;
}

extern(Windows)
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
  char[8] firstNumber;
  char[8] secondNumber;
  int count;
  long num1;
  long num2;

  switch (uMsg) {
    case WM_COMMAND: {
      switch (LOWORD(wParam)) {
        case IDC_BTN_PLUS:
          if (HIWORD(wParam) == BN_CLICKED) {
            count = SendMessageA(ghFirstNumberEdit, WM_GETTEXT, 
                                 6, cast(int)cast(char*)firstNumber);
            count = SendMessageA(ghSecondNumberEdit, WM_GETTEXT, 
                                 6, cast(int)cast(char*)secondNumber);
            num1 = atoi(cast(char[])firstNumber);
            num2 = atoi(cast(char[])secondNumber);
            SendMessageA(ghResultNumberEdit, WM_SETTEXT, 
                         8, cast(int)cast(char*)toString(num1 + num2));
          }
          break;
        case IDC_BTN_MINUS:
          if (HIWORD(wParam) == BN_CLICKED) {
            count = SendMessageA(ghFirstNumberEdit, 
                                 WM_GETTEXT, 8, 
                                 cast(int)cast(char*)firstNumber);
            count = SendMessageA(ghSecondNumberEdit, 
                                 WM_GETTEXT, 8, 
                                 cast(int)cast(char*)secondNumber);
            num1 = atoi(cast(char[])firstNumber);
            num2 = atoi(cast(char[])secondNumber);
            SendMessageA(ghResultNumberEdit, 
                         WM_SETTEXT, 8, 
                         cast(int)cast(char*)toString(num1 - num2));
          }
          break;
        case IDC_EDIT_FIRST_NUMBER:
          break;
        case IDC_EDIT_SECOND_NUMBER:
          break;
        case IDC_EDIT_RESULT_NUMBER:
          break;
      }
      break;
    }
    case WM_DESTROY:
      PostQuitMessage(0);

      break;

    case WM_NOTIFY:
      break;

    default:
      break;
  }
  return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}

TreeView

DescriptionDemonstrates basic usage of Win32 TreeView control. Creates very simple tree, and responds to mouse click selections with confirmation in TextViewer. Only uses Win32 api calls ... no GUI framework. Buttons created, but only 'stubbed' functionality. As o
Date/TimeSat Sep 25, 2004 9:25 am
Posted byLynn
/*
 *  Copyright (C) 2004 by Digital Mars, www.digitalmars.com
 *  Written by Lynn Allan by adapting code by Walter Bright
 *
 *  This software is provided 'as-is', without any express 
 *  or implied warranty. In no event will the authors be held
 *  liable for any damages arising from the use of this software.
 *
 *  Permission is granted to anyone to use this software for 
 *  any purpose, including commercial applications, and to alter
 *  it and redistribute it freely, subject to the following 
 *  restrictions:
 *
 *  o The origin of this software must not be misrepresented; 
 *    you must not claim that you wrote the original software.
 *    If you use this software in a product, an acknowledgment
 *    in the product documentation would be
 *    appreciated but is not required.
 *  o Altered source versions must be plainly marked as such,
 *    and must not be misrepresented as being the original
 *    software.
 *  o This notice may not be removed or altered from any source
 *    distribution.
 */

/* Compile with:
 *  dmd -O -release TreeView.d win32.lib gdi32.lib comctl32.lib TreeView.def
 *  or
 *  dmd -g -debug TreeView.d win32d.lib gdi32.lib comctl32.lib TreeView.def
 *
 * TreeView.def should contain:
 * EXETYPE NT
 * SUBSYSTEM WINDOWS
 */

import std.string;
import std.outbuffer;
import std.c.windows.windows;
import win32.commctrl;


const int IDC_BTN_BOOKS = 103;
const int IDC_BTN_SEARCH = 104;
const int IDC_EDIT_SEARCH_WORDS = 105;

const int IDC_EDIT_TEXT_VIEWER = 106;
const int IDC_BTN_OPTIONS = 107;
const int IDC_BTN_HELP = 108;

const int IDC_TREE_CHAP_SELECTOR = 109;
const int IDC_LIST_SEARCH_MATCHES_LIST = 110;

static HINSTANCE ghInstance;

static HWND      ghBooksBtn;
static HWND      ghChapSelectorTree;
static HWND      ghHelpBtn;
static HWND      ghOptionsBtn;
static HWND      ghSearchBtn;
static HWND      ghSearchWordsEdit;

static HWND      ghTextViewerEdit;
static HWND      ghWndMain;
static HTREEITEM gbHcsBook[68];

void CreateControls()
{
  HWND hChapSelectorTree;
  
  ghBooksBtn = CreateWindowA("BUTTON", "Books", 
                     WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                     5, 5, 53, 25, ghWndMain, 
                             cast(HMENU) IDC_BTN_BOOKS, ghInstance, null);
  ghSearchBtn = CreateWindowA("BUTTON", "Search", 
                      WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                      58, 5, 53, 25, ghWndMain, 
                      cast(HMENU) IDC_BTN_SEARCH, ghInstance, null);

  ghSearchWordsEdit = CreateWindowA("EDIT", "", 
                            WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                            115, 5, 145, 25, ghWndMain, 
                            cast(HMENU) IDC_EDIT_SEARCH_WORDS, ghInstance, null);

  ghOptionsBtn = CreateWindowA("BUTTON", "Options", 
                       WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                       265, 5, 53, 25, ghWndMain, 
                       cast(HMENU) IDC_BTN_OPTIONS, ghInstance, null);

  ghHelpBtn = CreateWindowA("BUTTON", "Help", 
                            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                            320, 5, 53, 25, ghWndMain, 
                            cast(HMENU) IDC_BTN_HELP, ghInstance, null);

  ghTextViewerEdit = CreateWindowA("EDIT", "", 
                           WS_CHILD | WS_VISIBLE | WS_BORDER 
                           | ES_AUTOVSCROLL | WS_VSCROLL
                           | ES_LEFT | ES_MULTILINE | ES_NOHIDESEL,
                           115, 32, 260, 300, ghWndMain, 
                           cast(HMENU) IDC_EDIT_TEXT_VIEWER, ghInstance, null);

  SendMessageA(ghTextViewerEdit, WM_SETTEXT, 0, 

      cast(int)cast(char*)"Hello\x0D\x0A"
                          "Line 2\x0D\x0A"
                          "Line 3\x0D\x0A"

                          "Long Line 4 to check word wrap aaa bbb ccc ddd eee "
                          "fff ggg hhh iii jjj kkk lll mmm\x0D\x0A"
                          "Line 5\x0D\x0A"
                          "Line 6");


  InitCommonControls();

  hChapSelectorTree = CreateWindowA("SYSTREEVIEW32", "", 
                            WS_CHILD | WS_VISIBLE | WS_BORDER | TVS_HASLINES |
                            WS_CLIPSIBLINGS | TVS_HASBUTTONS | TVS_LINESATROOT,
                            5, 32, 110, 300, ghWndMain, 
                            cast(HMENU) IDC_TREE_CHAP_SELECTOR, ghInstance, null);
  if (hChapSelectorTree == null) {
    MessageBoxA(null, cast(char *)("ChapSelector Tree not created!"), 
                "Error", MB_OK | MB_ICONEXCLAMATION);
  }
  else {
    ghChapSelectorTree = hChapSelectorTree;
  }
}


void DoMessagePump()
{
  MSG msg;
  while (GetMessageA(&msg, cast(HWND) null, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessageA(&msg);
  }
}


void CreateMainWindow()
{
  HWND hWnd;
  hWnd = CreateWindowA("DWndClass", "TreeView Example", 
               WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX 
               | WS_SYSMENU | WS_VISIBLE,
               CW_USEDEFAULT, CW_USEDEFAULT, 385, 375, HWND_DESKTOP,
               cast(HMENU) null, ghInstance, null);
  assert(hWnd);
  ghWndMain = hWnd;
}


void InitApplication()
{
  WNDCLASS wc;
  wc.lpszClassName = "DWndClass";
  wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = &WindowProc;
  wc.hInstance = ghInstance;
  wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
  wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
  wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = null;
  wc.cbClsExtra = wc.cbWndExtra = 0;


  assert(RegisterClassA(&wc));
}

void InitInstance()
{
  ghInstance = GetModuleHandleA(null);
  InitApplication();

  CreateMainWindow();

  CreateControls();

  LoadChapSelector();
}

void LoadChapterText(LPARAM lParam)
{
  LPNM_TREEVIEWA pnmtv = cast(LPNM_TREEVIEWA) lParam;
  TV_ITEMA tvI;
  char szText[256];

  tvI.mask = TVIF_TEXT | TVIF_PARAM;
  tvI.pszText = szText;
  tvI.cchTextMax = 32;
  tvI.hItem = pnmtv.itemNew.hItem;

  SendMessageA(ghChapSelectorTree, TVM_GETITEM, 0, 

               cast(int)cast(TV_ITEMA*)&tvI);

  OutBuffer buf = new OutBuffer;
  buf.reserve(32);
  buf.write(toString(tvI.pszText));
  buf.write(" = ");
  buf.write(toString(tvI.lParam));

  SendMessageA(ghTextViewerEdit, WM_SETTEXT, 0, 

               cast(int)cast(char*)buf.toString());
}

void LoadBook(int bookNum, char[] bookName, 
              char[] bookAbbrev, int chapCount)
{
  TV_ITEMA tvI;
  TV_INSERTSTRUCTA tvIns;

  tvI.mask = TVIF_TEXT | TVIF_PARAM;
  tvI.pszText = bookName;
  tvI.cchTextMax = 10;
  tvI.lParam = bookNum * 1000;
  tvIns.item = tvI;
  tvIns.hInsertAfter = cast(HTREEITEM)TVI_ROOT;
  tvIns.hParent = null;
  gbHcsBook[bookNum] = cast(HTREEITEM)SendMessageA(ghChapSelectorTree, 
                                                   TVM_INSERTITEM, 0, 

                                                   cast(int)&tvIns);

  tvI.cChildren = 0;

  tvIns.hParent = gbHcsBook[bookNum];
  tvIns.hInsertAfter = cast(HTREEITEM)TVI_LAST;

  for (int i = 1; i <= chapCount; ++i) {
    tvI.pszText = bookAbbrev ~ "." ~ toString(i);
    tvI.lParam = bookNum * 1000 + i;
    tvIns.item = tvI;
    SendMessageA(ghChapSelectorTree, 
                 TVM_INSERTITEM, 0, 

                 cast(int)&tvIns);
  }
}

void LoadChapSelector()
{
  LoadBook(1, "Genesis", "Gen", 10);
  LoadBook(2, "Exodus", "Exo", 8);
  LoadBook(3, "Leviticus", "Lev", 4);
  LoadBook(4, "Numbers", "Num", 6);
}


/**********************************************************/

/* Note the similarity of this code to the console D startup
 * code in \dmd\src\phobos\dmain2.d
 * You'll also need a .def file with at least the following in it:
 *  EXETYPE NT
 *  SUBSYSTEM WINDOWS
 */

extern (C) void gc_init();
extern (C) void gc_term();

extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleUnitTests();


extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
            LPSTR lpCmdLine, int nCmdShow)
{
  int result = 1;

  gc_init();    // initialize garbage collector
  _minit();     // initialize module constructor table

  try {
    _moduleCtor();      // call module constructors
    _moduleUnitTests(); // run unit tests (optional)

    InitInstance();
  DoMessagePump();
  }
  catch (Object o) {    // catch any uncaught exceptions

    MessageBoxA(null, cast(char *)o.toString(), "Error",
                MB_OK | MB_ICONEXCLAMATION);
    result = 0;   // failed
  }
  gc_term();      // run finalizers; terminate garbage collector

  return result;
}

extern(Windows)
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
  LPNMHDR  pnmhdr;

  switch (uMsg) {
    case WM_COMMAND: {
      switch (LOWORD(wParam)) {
        case IDC_BTN_BOOKS:
          if (HIWORD(wParam) == BN_CLICKED) {
            MessageBoxA(hWnd, "Clicked", "Books",
                        MB_OK | MB_ICONINFORMATION);
          }
          break;
        case IDC_BTN_SEARCH:
          if (HIWORD(wParam) == BN_CLICKED) {
            MessageBoxA(hWnd, "Clicked", "Search",
                        MB_OK | MB_ICONEXCLAMATION);
          }
          break;
        case IDC_BTN_OPTIONS:
          if (HIWORD(wParam) == BN_CLICKED) {
            MessageBoxA(hWnd, "Clicked", "Options",
                        MB_OK | MB_ICONEXCLAMATION);
          }
          break;
        case IDC_BTN_HELP:
          if (HIWORD(wParam) == BN_CLICKED) {
            MessageBoxA(hWnd, "Clicked", "Help",
                        MB_OK | MB_ICONEXCLAMATION);
          }
          break;
        case IDC_EDIT_SEARCH_WORDS:
          if (HIWORD(wParam) == BN_CLICKED) {
            MessageBoxA(hWnd, "Clicked", "Search Words",
                        MB_OK | MB_ICONEXCLAMATION);
          }
          break;
        case IDC_EDIT_TEXT_VIEWER:
          if (HIWORD(wParam) == BN_CLICKED) {
            MessageBoxA(hWnd, "Clicked", "Text Viewer",
                        MB_OK | MB_ICONEXCLAMATION);
          }
          break;
      }
      break;
    }
    case WM_DESTROY:
      PostQuitMessage(0);

      break;

    case WM_NOTIFY:
      pnmhdr = cast(LPNMHDR)lParam;
      if (pnmhdr.hwndFrom == cast(HANDLE)ghChapSelectorTree) {
        UINT code = pnmhdr.code;
        if (code == TVN_SELCHANGED || code == TVN_KEYDOWN) {
          LoadChapterText(lParam);
        }
      }
      break;

    default:
      break;
  }
  return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}

MiniCalc - RestorePosition

DescriptionSimple windows app that stores it upper-left coordinates in registry so that it can remember where it was when the app was closed.
Date/TimeThu Oct 14, 2004 10:35 am
Posted byLynn
/*
 *  Copyright (C) 2004 by Digital Mars, www.digitalmars.com
 *  Written by Lynn Allan
 *  This software is provided 'as-is'. Released to public domain.
 *
 * Compile with:
 *  dmd MiniCalc.d gdi32.lib advapi32.lib MiniCalc.def
 *
 * You'll also need a .def file with at least the following in it:
 *  EXETYPE NT
 *  SUBSYSTEM WINDOWS
 *
 * Current as of dmd ver 0.102. In the basic dmd distribution, there
 *   are missing extern definitions for registry and windowplacement
 *   constants and structures. For now, these have been provided. There
 *   are auxillary files registry.d and win32.commctrl.d that will 
 *   probably eventually be included with the standard phobos distribution.
 */

import std.string;
import std.c.windows.windows;

private enum {
IDC_BTN_PLUS = 103,
IDC_BTN_MINUS,
IDC_EDIT_FIRST_NUMBER,
IDC_EDIT_SECOND_NUMBER,
IDC_EDIT_RESULT_NUMBER
}


private HINSTANCE ghInstance;
private HWND      ghPlusBtn;
private HWND      ghMinusBtn;
private HWND      ghFirstNumberEdit;
private HWND      ghSecondNumberEdit;
private HWND      ghResultNumberEdit;

private HWND      ghWndMain;

private int gDlgTop;
private int gDlgLeft;

void CreateControls()
{
  HWND hChapSelectorTree;
  
  ghPlusBtn = CreateWindowA("BUTTON", "Plus", 
                 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                 5, 5, 53, 25, ghWndMain, cast(HMENU) IDC_BTN_PLUS, 
                 ghInstance, null);

  ghMinusBtn = CreateWindowA("BUTTON", "Minus", 
                 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                 60, 5, 53, 25, ghWndMain, 
                 cast(HMENU) IDC_BTN_MINUS, 
                 ghInstance, null);

  ghFirstNumberEdit = CreateWindowA("EDIT", toString(gDlgLeft), 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 32, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_FIRST_NUMBER, ghInstance, null);

  ghSecondNumberEdit = CreateWindowA("EDIT", toString(gDlgTop), 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 60, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_SECOND_NUMBER, ghInstance, null);
  
  ghResultNumberEdit = CreateWindowA("EDIT", "", 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 87, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_RESULT_NUMBER, 
                 ghInstance, null);
}


void DoMessagePump()
{
  MSG msg;
  while (GetMessageA(&msg, cast(HWND) null, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessageA(&msg);
  }
}


void CreateMainWindow()
{
  HWND hWnd;
  hWnd = CreateWindowA("DWndClass", 
               "MiniCalc", 
               WS_THICKFRAME | WS_MAXIMIZEBOX 
               | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE,
               gDlgLeft, gDlgTop,
               125, 150,       // width & height
               HWND_DESKTOP,
               cast(HMENU) null, ghInstance, null);
  assert(hWnd);
  ghWndMain = hWnd;
}


void InitApplication()
{
  WNDCLASS wc;
  wc.lpszClassName = "DWndClass";
  wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = &WindowProc;
  wc.hInstance = ghInstance;
  wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
  wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
  wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = null;
  wc.cbClsExtra = wc.cbWndExtra = 0;


  assert(RegisterClassA(&wc));
}

void InitInstance()
{
  ghInstance = GetModuleHandleA(null);
  InitApplication();

  InitRegistry();

  CreateMainWindow();

  CreateControls();
}

extern (Windows)   // Not defined in windows.d ... use Core32
{
LONG RegQueryValueExA(HKEY hkey, 
                      LPCTSTR keyName, 
                      LPDWORD reservedNull,
                      LPDWORD type, 
                      void*   data,
                      LPDWORD len);


struct WINDOWPLACEMENT {
    UINT  length;
    UINT  flags;
    UINT  showCmd;
    POINT ptMinPosition;
    POINT ptMaxPosition;
    RECT  rcNormalPosition;
}
BOOL GetWindowPlacement(HWND hWnd,WINDOWPLACEMENT *lpwndpl);
}

private void InitRegistry()
{
  HKEY hkey;
  LONG result;
  DWORD dwType;
  const int BUF_SZ = 4;
  DWORD dwLen = BUF_SZ;
  DWORD displosition;

  result = RegCreateKeyExA(HKEY_CURRENT_USER, 
                           "Software\\dSource\\MiniCalc\\Settings", 
                           cast(uint)null,
                           null,
                           REG_OPTION_NON_VOLATILE,
                           KEY_ALL_ACCESS,
                           null,
                           &hkey,
                           &displosition);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  result = RegCloseKey(hkey);
  assert(result == ERROR_SUCCESS);

  result = RegOpenKeyA(HKEY_CURRENT_USER, 
                       "Software\\dSource\\MiniCalc\\Settings", &hkey);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  try {
    dwLen = 4;
    result = RegQueryValueExA(hkey, 
                              cast(char*)"DlgTop", 
                              null, 
                              &dwType, 
                              cast(void*)&gDlgTop, 
                              &dwLen); 
    assert(result == ERROR_SUCCESS);

    result = RegQueryValueExA(hkey, 
                              cast(char*)"DlgLeft", 
                              null, 
                              &dwType, 
                              cast(void*)&gDlgLeft, 
                              &dwLen); 
    assert(result == ERROR_SUCCESS);
  }
  catch(Object o) {
    gDlgLeft = 400;
    gDlgTop  = 50;
  }
  result = RegCloseKey(hkey);
  assert(result == ERROR_SUCCESS);
}


private void SaveRegistrySettings()
{
  DWORD dwLen;
  HKEY  hkey;
  LONG  result;

  result = RegOpenKeyA(HKEY_CURRENT_USER, 
                       "Software\\dSource\\MiniCalc\\Settings", 
                       &hkey);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  dwLen = 4;
  result = RegSetValueExA(hkey, 
                          cast(char*)"DlgTop", 
                          0, 

                          REG_DWORD, 
                          cast(BYTE*)&gDlgTop, 
                          dwLen);
  assert(result == ERROR_SUCCESS);

  result = RegSetValueExA(hkey, 
                          cast(char*)"DlgLeft", 
                          0, 
                          REG_DWORD, 
                          cast(BYTE*)&gDlgLeft, 
                          dwLen);
  assert(result == ERROR_SUCCESS);

  result = RegCloseKey(hkey);
  assert(result == ERROR_SUCCESS);
}


private void GetCurrentMainWindowPosition()
in { assert(ghWndMain != null); }
body {
  WINDOWPLACEMENT windowPlacement;
  int flag  = GetWindowPlacement(ghWndMain, &windowPlacement);
  assert (flag != 0);

  debug { int _dbg_left = windowPlacement.rcNormalPosition.left; }
  gDlgLeft = windowPlacement.rcNormalPosition.left;
  gDlgTop  = windowPlacement.rcNormalPosition.top;
}

/**********************************************************/

extern (C) void gc_init();

extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();

extern (C) void _moduleUnitTests();

extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
            LPSTR lpCmdLine, int nCmdShow)
{
  int result = 1;

  gc_init();      // initialize garbage collector

  _minit();     // initialize module constructor table

  try {
    _moduleCtor();    // call module constructors
    _moduleUnitTests(); // run unit tests (optional)

    InitInstance();
    DoMessagePump();
  }
  catch (Object o) {    // catch any uncaught exceptions

    MessageBoxA(null, cast(char *)o.toString(), "Error",
                MB_OK | MB_ICONEXCLAMATION);
    result = 0;   // failed
  }
  gc_term();      // run finalizers; terminate garbage collector

  return result;
}

extern(Windows)
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
  char[8] firstNumber;
  char[8] secondNumber;
  int count;
  long num1;
  long num2;

  switch (uMsg) {
    case WM_COMMAND: {
      switch (LOWORD(wParam)) {
        case IDC_BTN_PLUS:
          if (HIWORD(wParam) == BN_CLICKED) {
            count = SendMessageA(ghFirstNumberEdit, WM_GETTEXT, 
                                 6, cast(int)cast(char*)firstNumber);
            count = SendMessageA(ghSecondNumberEdit, WM_GETTEXT, 
                                 6, cast(int)cast(char*)secondNumber);
            num1 = atoi(cast(char[])firstNumber);
            num2 = atoi(cast(char[])secondNumber);
            SendMessageA(ghResultNumberEdit, WM_SETTEXT, 
                         8, cast(int)cast(char*)toString(num1 + num2));
          }
          break;
        case IDC_BTN_MINUS:
          if (HIWORD(wParam) == BN_CLICKED) {
            count = SendMessageA(ghFirstNumberEdit, 
                                 WM_GETTEXT, 8, 
                                 cast(int)cast(char*)firstNumber);
            count = SendMessageA(ghSecondNumberEdit, 
                                 WM_GETTEXT, 8, 
                                 cast(int)cast(char*)secondNumber);
            num1 = atoi(cast(char[])firstNumber);
            num2 = atoi(cast(char[])secondNumber);
            SendMessageA(ghResultNumberEdit, 
                         WM_SETTEXT, 8, 
                         cast(int)cast(char*)toString(num1 - num2));
          }
          break;
        case IDC_EDIT_FIRST_NUMBER:
          break;
        case IDC_EDIT_SECOND_NUMBER:
          break;
        case IDC_EDIT_RESULT_NUMBER:
          break;
      }
      break;
    }
    case WM_DESTROY:
      GetCurrentMainWindowPosition();
      SaveRegistrySettings();
      PostQuitMessage(0);

      break;

    case WM_NOTIFY:
      break;

    default:
      break;
  }
  return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}

jcc7(rank = 0, level = 1)