Sunday, March 10, 2013

ZK Textbox with Codemirror


Introduction

This article describe how to make ZK textbox working with Codemirror.

Pre-request

Load External Javascript and CSS Files in ZK
http://ben-bai.blogspot.tw/2013/03/zk-basic-load-external-javascript-and.html

Codemirror Getting Started
http://ben-bai.blogspot.tw/2013/03/web-code-editor-codemirror-getting.html

The Program

textbox_codemirror.zul

A multiline ZK Textbox (with textarea dom element), bind the onblur of codemirror to onchange of textbox.

<?script type="text/javascript" src="resources/js/libsAndTools/codemirror/lib/codemirror.js"?>
<?style href="resources/js/libsAndTools/codemirror/lib/codemirror.css" type="text/css" ?>
<?script type="text/javascript" src="resources/js/libsAndTools/codemirror/mode/javascript/javascript.js"?>
<zk xmlns:w="client">
    <window title="ZK Textbox Codemirror Test" border="normal">
        <div width="300px" height="250px" style="overflow: hidden;">
            <textbox id="tbx" rows="10">
                <attribute w:name="bind_"><![CDATA[
                    function (a, b, c) {
                        this.$bind_(a, b, c);
                        var wgt = this;
                        myCodeMirror = CodeMirror.fromTextArea(this.$n());
                        myCodeMirror.on('blur', function () {
                            var val = myCodeMirror.getValue();
                            wgt.$n().value = val;
                            wgt.fire('onChange', {value: val}, {toServer: true});
                        });
                    }
                ]]></attribute>
            </textbox>
        </div>
        <button label="test" onClick="alert(tbx.getValue());" />
        <button label="execute">
            <attribute name="onClick"><![CDATA[
                Clients.evalJavaScript(tbx.getValue());
            ]]></attribute>
        </button>
    </window>
</zk>


The Result

View demo online
http://screencast.com/t/ZQMHIJj8

Download

textbox_codemirror.zul
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/WebContent/textbox_codemirror.zul

Demo Flash
https://github.com/benbai123/ZK_Practice/blob/master/Components/demos/ZK_Textbox_Codemirror.swf

ZK Basic: Load External Javascript and CSS Files


Introduction

This article describe how to load external javascript and css files in ZK.

Project Structure

The external css and js files are under WebContent folder as below



The Program

load_external_js_css.zul

A native button apply the custom class 'custom-button' defined in external css file 'WebContent/resources/css/test.css', calling custom javascript function 'customjs.sayHello' defined in external js file 'WebContent/resources/js/test.js'

<!-- load .js file under WebContent -->
<?script type="text/javascript" src="resources/js/test.js"?>
<!-- load .css file under WebContent -->
<?style href="resources/css/test.css" type="text/css" ?>
<zk xmlns:n="native">
    <!-- a native (pure html) button,
        apply custom css style,
        call the custom js function when clicked-->
    <n:button class="custom-button"
        onclick="customjs.sayHello('Ben');">
        test
    </n:button>
</zk>


The Result

Page loaded



Button clicked



Reference

The script directive
http://books.zkoss.org/wiki/ZUML_Reference/ZUML/Processing_Instructions/script

The style directive
http://books.zkoss.org/wiki/ZUML%20Reference/ZUML/Processing%20Instructions/style

Download

load_external_js_css.zul
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/WebContent/load_external_js_css.zul

test.js
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/WebContent/resources/js/test.js

test.css
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/WebContent/resources/css/test.css

Saturday, March 9, 2013

Web Code Editor: Codemirror, Getting Started


Introduction

From official site:
CodeMirror is a JavaScript component that provides a code editor in the browser. When a mode is available for the language you are coding in, it will color your code, and optionally help with indentation.

Setup

1. Go to official site and click "Download the latest release" to download the latest release.



2. Unzip the downloaded file, copy the lib folder and mode folder to your web project as needed.



The Program

codemirror_gettingstarted.html

<html>
    <head>
        <script src="lib/codemirror.js"></script>
        <link rel="stylesheet" href="lib/codemirror.css">
        <script src="mode/javascript/javascript.js"></script>
        <script src="mode/clike/clike.js"></script>
        <style>
            .CodeMirror {
                height: 150px;
            }
        </style>
        <script type="text/javascript">
            // do after window is loaded
            window.onload = function () {
                // jsTextarea: the dom element, textarea with id 'jsTextarea'
                // clikeTextarea: the dom element, textarea with id 'clikeTextarea'
                // jsCodeMirror: code-editor with mode 'javascript'
                // clikeCodeMirror: code-editor with mode 'clike'
                var jsTextarea = document.getElementById('jsTextarea'),
                    clikeTextarea = document.getElementById('clikeTextarea'),
                    jsCodeMirror = CodeMirror.fromTextArea(jsTextarea, {mode: "javascript"}),
                    clikeCodeMirror = CodeMirror.fromTextArea(clikeTextarea, {mode: "clike"});
                // sync value while blur code-editor
                jsCodeMirror.on('blur', function () {
                    jsTextarea.value = jsCodeMirror.getValue();
                });
                clikeCodeMirror.on('blur', function () {
                    clikeTextarea.value = clikeCodeMirror.getValue();
                });
            }
            // show textarea value
            function showJsContent () {
                alert(document.getElementById('jsTextarea').value);
            }
            function showClikeContent () {
                alert(document.getElementById('clikeTextarea').value);
            }
        </script>
    </head>
    <body>
        js:
        <textarea id="jsTextarea"></textarea>
        <button onclick="showJsContent()">show js content</button><br />
        clike:
        <textarea id="clikeTextarea" /></textarea>
        <button onclick="showClikeContent()">show clike content</button>
    </body>
</html>


The Result

View demo on line
http://screencast.com/t/SuOGRLjLjR

Reference

Official site
http://codemirror.net/

User Manual
http://codemirror.net/doc/manual.html

Download

codemirror_gettingstarted.html
https://github.com/benbai123/HTML_CSS_Javascript_practice/blob/master/libs_tools/codemirror/test/codemirror_gettingstarted.html

Demo flash
https://github.com/benbai123/HTML_CSS_Javascript_practice/blob/master/demos/libs_tools/codemirror/codemirror_gettingstarted.swf

Monday, February 25, 2013

ZK Drag and Drop: Make Everything Resizable


Introduction

In ZK, some comopnents like textbox, button, link are not resizable, this article describe how to use a draggable div to make those non resizable components resizable.

The Program

make_components_resizable.zul

A resizer div and several custom resizable components in this page, will display the resizer div while mouseover the right-side or the bottom of custom resizable component, fire event while resizer div is dragged to resize component.

<!-- 
    Tested with ZK 6.0.2 (Chrome, IE9)
 -->
<zk xmlns:w="client">
    <style>
        .custom-sizer {
            position: absolute;
            display: none;
            border: 4px solid #aaa;
            z-index: 999999;
        }
        .custom-resizable-comp {
            display: block;
        }
    </style>
    <script><![CDATA[
        // get the dom element of custom resizer div
        function _getCustomResizer () {
            return jq('.custom-sizer')[0];
        }
        // hide the custom resizer div
        function _hideCustomResizer () {
            if (!zk.Widget.customResizing)
                _getCustomResizer().style.display = 'none';
        }
        // override zk.Widget to make components resizable
        zk.afterLoad("zul", function () {
            var _wgt = {};
            zk.override(zk.Widget.prototype, _wgt, {
                doMouseMove_: function (evt) {
                    _wgt.doMouseMove_.apply(this, arguments);
                    // do nothing if resizing
                    if (zk.Widget.customResizing) return;
                    // is custom resizable component
                    if (this._isResizable()) {
                        // keep widget instance
                        zk.Widget.customResizableWidget = this;
                        // at the right side of the component
                        if (this._atRightSide(evt)) {
                            // keep 'resizing width'
                            zk.Widget.customResizableWidgetDir = 'w';
                            // show custom resizer as vertical bar
                            // at the right side of this component
                            this._showRightResizer();
                        } else if (this._atBottom(evt)) { // at bottom of the component
                            // keep 'resizing height'
                            zk.Widget.customResizableWidgetDir = 'h';
                            // show custom resizer as horizontal bar
                            // at the bottom of this component
                            this._showBottomResizer();
                        } else { // not close to right side/bottom
                            // hide custom resizer
                            _hideCustomResizer();
                        }
                    }
                },
                // is resizable if has the specific class
                // 'custom-resizable-comp'
                _isResizable: function () {
                    return jq(this.$n()).hasClass('custom-resizable-comp');
                },
                // the mouse cursor is near the right side of component
                _atRightSide: function (evt) {
                    var left = evt.pageX, // cursor x position
                        $n = jq(this.$n()),
                        wRight = $n.offset().left + $n.width(); // the right side of component
                    // their distance is smaller than 3px
                    return (Math.abs(left - wRight) < 3);
                },
                // the mouse cursor is near the bottom of component
                _atBottom: function (evt) {
                    var top = evt.pageY, // cursor y position
                        $n = jq(this.$n()),
                        wBottom = $n.offset().top + $n.height(); // the bottom of component
                    // their distance is smaller than 3px
                    return (Math.abs(top - wBottom) < 3);
                },
                // display custom resizer at the right side of component
                _showRightResizer: function () {
                    // do nothing if resizing
                    if (zk.Widget.customResizing) return;
                    var resizer = _getCustomResizer(),
                        rstyle = resizer.style,
                        $n = jq(this.$n()),
                        noffset = $n.offset();

                    // adjust the position of custom resizer
                    rstyle.left = noffset.left + $n.width() + 'px';
                    rstyle.top = noffset.top + 'px';
                    // adjust the size of custom resizer
                    rstyle.width = '0px';
                    rstyle.height = $n.height() + 'px';
                    // adjust cursor and show custom resizer
                    rstyle.cursor = 'e-resize';
                    rstyle.display = 'block';
                },
                _showBottomResizer: function () {
                    if (zk.Widget.customResizing) return;
                    var resizer = _getCustomResizer(),
                        rstyle = resizer.style,
                        $n = jq(this.$n()),
                        noffset = $n.offset();
    
                    // adjust the position of custom resizer
                    rstyle.left = noffset.left + 'px';
                    rstyle.top = noffset.top + $n.height() + 'px';
                    // adjust the size of custom resizer
                    rstyle.width = $n.width() + 'px';
                    rstyle.height = '0px';
                    // adjust cursor and show custom resizer
                    rstyle.cursor = 's-resize';
                    rstyle.display = 'block';
                }
            });
        });
    ]]></script>
    <div id="customSizer" sclass="custom-sizer" draggable="true" use="test.custom.component.div.CustomResizer">
        <attribute w:name="doMouseOut_"><![CDATA[
            function (evt) {
                // hide custom resizer if mouseout it
                this.$doMouseOut_(evt);
                _hideCustomResizer();
            }
        ]]></attribute>
        <attribute w:name="getDragOptions_"><![CDATA[
            function (map) {
                var dragOptions = {};
                for (var key in map) {
                    dragOptions[key] = map[key];
                }
                var oldBeforeSizing = dragOptions.starteffect,
                    oldAfterSizing = dragOptions.endeffect,
                    oldDragging = dragOptions.change;
                // at the beginning of dragging
                dragOptions.starteffect = function (dg) {
                    // mark resizing
                    zk.Widget.customResizing = true;
                    // save the starting x position if resizing width
                    // or save the starting y position if resizing height
                    dg._delta = zk.Widget.customResizableWidgetDir == 'w'?
                            dg._currentDelta()[0] : dg._currentDelta()[1];
                    // do original function
                    oldBeforeSizing(dg);
                };
                // at the end of dragging
                dragOptions.endeffect = function (dg, evt) {
                    // remove resizing mark
                    zk.Widget.customResizing = false;
                    // get resizing direction (w: width, h: height)
                    // evaluate new size
                    // get the uuid of the component to resize
                    var resizeWidth = zk.Widget.customResizableWidgetDir == 'w',
                        $szwgt = jq(zk.Widget.customResizableWidget),
                        delta = resizeWidth?
                            (dg._currentDelta()[0] - dg._delta) : (dg._currentDelta()[1] - dg._delta),
                        newValue = resizeWidth?
                            ($szwgt.width() + delta) : ($szwgt.height() + delta),
                        uuid = zk.Widget.customResizableWidget.uuid,
                        data;
                    if (newValue <= 0) newValue = 1;
                    // fire onCustomResize event to custom resizer
                    // 'value', 'reference' and 'resizeAttribute' are
                    // the keys of data map
                    data = {value: newValue,
                            reference: uuid,
                            resizeAttribute: (resizeWidth? 'width' : 'height')};
                    zk.Widget.$('$customSizer').fire('onCustomResize', data);
                    // call original function
                    oldAfterSizing(dg, evt);
                    // hide custom resizer
                    _getCustomResizer().style.display = 'none';
                };
                // while dragging
                dragOptions.change = function (drag, pt, evt) {
                    // call original function
                    oldDragging(drag, pt, evt);
                    var wgt = drag.control,
                        n = wgt.$n(),
                        $szwgt = jq(zk.Widget.customResizableWidget);
                    if (n.style.display != 'block') n.style.display = 'block';
                    // keep 'top' unchanged and make 'left' follow mouse position
                    // if resizing width,
                    // keep 'left' unchanged and make 'top' follow mouse position
                    // if resizing height,
                    n.style.left = (zk.Widget.customResizableWidgetDir == 'h'?
                            $szwgt.offset().left+'px' : evt.pageX+'px');
                    n.style.top = (zk.Widget.customResizableWidgetDir == 'w'?
                            $szwgt.offset().top+'px' : evt.pageY+'px');
                }
                // clear ghosting function to
                // avoid the faker dom element while dragging
                dragOptions.ghosting = null;
                return dragOptions;
            }
        ]]></attribute>
    </div>
    <vlayout>
        <hlayout>
            <textbox sclass="custom-resizable-comp"
                value="resizable textbox" />
            <checkbox sclass="custom-resizable-comp"
                label="resizable checkbox" />
            <vlayout>
                <a sclass="custom-resizable-comp"
                    href="http://www.zkoss.org">
                    resizable link
                </a>
                resizable menubar
                <menubar sclass="custom-resizable-comp">
                    <menu sclass="custom-resizable-comp" label="File (resizable)">
                        <menupopup sclass="custom-resizable-comp">
                            <menuitem sclass="custom-resizable-comp" label="New (resizable)" onClick="alert(self.label)"/>
                            <menuitem sclass="custom-resizable-comp" label="Exit (resizable)" onClick="alert(self.label)"/>
                        </menupopup>
                    </menu>
                </menubar>
            </vlayout>
        </hlayout>
        <button sclass="custom-resizable-comp"
            mold="trendy"
            label="resizable button" />
    </vlayout>
</zk>


CustomResizer.java

The class extends div, listening to custom resize event and resizing component as needed.

package test.custom.component.div;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Div;
import org.zkoss.zul.impl.XulElement;

import test.custom.component.event.CustomResizeEvent;

/**
 * Tested with ZK 6.0.2
 * @author benbai123
 *
 */
public class CustomResizer extends Div {
    private static final long serialVersionUID = 5597493971151879186L;

    static {
        // listen to custom resize event
        addClientEvent(CustomResizer.class, CustomResizeEvent.ON_CUSTOM_RESIZE, CE_DUPLICATE_IGNORE
                | CE_IMPORTANT | CE_NON_DEFERRABLE);
    }
    public void service(org.zkoss.zk.au.AuRequest request, boolean everError) {
        final String cmd = request.getCommand();

        // custom resize event
        if (CustomResizeEvent.ON_CUSTOM_RESIZE.equals(cmd)) {
            CustomResizeEvent evt = CustomResizeEvent.getCustomResizeEvent(request);
            // get the component to resize
            Component ref = evt.getReference();
            if (ref != null) {
                // get new size
                int value = evt.getValue();
                // get direction (width/height)
                String dir = evt.getResizeAttribute();
                // do resize
                if ("width".equals(dir)) {
                    if (ref instanceof XulElement) {
                        ((XulElement)ref).setWidth(value+"px");
                    } else if (ref instanceof HtmlBasedComponent) {
                        ((HtmlBasedComponent)ref).setWidth(value+"px");
                    } 
                } else if ("height".equals(dir)) {
                    if (ref instanceof XulElement) {
                        ((XulElement)ref).setHeight(value+"px");
                    } else if (ref instanceof HtmlBasedComponent) {
                        ((HtmlBasedComponent)ref).setHeight(value+"px");
                    } 
                }
            }
            // post event
            Events.postEvent(evt);
        } else {
            super.service(request, everError);
        }
    }
}


CustomResizeEvent.java

Used to keep the data of custom resize event.

package test.custom.component.event;

import java.util.Map;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;

/**
 * Tested with ZK 6.0.2
 * Basically you can think an Event object
 * is just a POJO to keep the data within an event
 * @author benbai123
 *
 */
public class CustomResizeEvent extends Event {
    private static final long serialVersionUID = -8839289786864776054L;

    public static final String ON_CUSTOM_RESIZE = "onCustomResize";
    private int _value;
    private final Component _reference;
    private String _resizeAttribute;
    @SuppressWarnings("rawtypes")
    public static CustomResizeEvent getCustomResizeEvent (org.zkoss.zk.au.AuRequest request) {
        // get data map
        Map data = request.getData();
        // get values by keys
        int value = (Integer)data.get("value");
        final Component reference = request.getDesktop().getComponentByUuidIfAny((String)data.get("reference"));
        String resizeAttribute = (String)data.get("resizeAttribute");
        // create event instance, return it
        return new CustomResizeEvent(ON_CUSTOM_RESIZE, request.getComponent(), value, reference, resizeAttribute);
    }
    // Constructor
    public CustomResizeEvent (String name, Component target,
            int value, Component reference, String resizeAttribute) {
        super(name, target);
        _value = value;
        _reference = reference;
        _resizeAttribute = resizeAttribute;
    }
    // getters
    public int getValue () {
        return _value;
    }
    public Component getReference () {
        return _reference;
    }
    public String getResizeAttribute () {
        return _resizeAttribute;
    }
}


The Result

View demo on line
http://screencast.com/t/DxeGJvPlWw

Reference

Source code of widget.js
https://github.com/zkoss/zk/blob/6.0/zk/src/archive/web/js/zk/widget.js

Source code of drag.js
https://github.com/zkoss/zk/blob/6.0/zk/src/archive/web/js/zk/drag.js

ZK Client Side Programming
http://books.zkoss.org/wiki/Small_Talks/2010/April/Client_Side_Programming

Download

make_components_resizable.zul
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/WebContent/make_components_resizable.zul

CustomResizer.java
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/src/test/custom/component/div/CustomResizer.java

CustomResizeEvent.java
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/src/test/custom/component/event/CustomResizeEvent.java

Demo Flash
https://github.com/benbai123/ZK_Practice/blob/master/Components/demos/make_components_resizable.swf

Friday, February 22, 2013

C String: String Concat (Simple Note)


Simple Note

Code

#include <stdio.h>
#include <string.h>
/**
 * 
 * Tested with Dev-C++ 4.9.9.2
 *  
 * Practice of string copy and concat.
 * char * strcat ( char * destination, const char * source );
 *         Appends a copy of the source string to the destination string
 *         plus a terminating null-character if source contains null-character.
 * char * strncat ( char * destination, char * source, size_t num );
 *         Appends the first num characters of source to destination,
 *         plus a terminating null-character.
 *
 * Note: 
 * 
 */
int main () {
    // a char array without '\0'
    char chArr[4] = {'a', 'b', 'c', 'd'};
    char chArrTwo[20] = "mnopq";
    char chArrThree[] = "abcd";
    char chArrFour[20] = "wxyz";

    // the source (chArr) doesn't have null-char ('\0')
    // will become wrong value after first concat
    printf("original: %s\n", chArrTwo);
    strcat(chArrTwo, chArr); // <-- the line above
    // change the line above to the line below then everything should be okay.
    // strncat(chArrTwo, chArr, 4); // <-- the line below
    printf("append abcd: %s\n", chArrTwo);
    strncat(chArrTwo, chArr, 2);
    printf("append ab: %s\n\n", chArrTwo);

    // the source (chArrThree) contains null-char ('\0')
    // everything should be okay
    printf("original: %s\n", chArrFour);
    strcat(chArrFour, chArrThree);
    printf("append abcd: %s\n", chArrFour);
    strncat(chArrFour, chArrThree, 2);
    printf("append ab: %s\n\n", chArrFour);

    system("PAUSE");
}

Result



References

strcat
http://www.cplusplus.com/reference/cstring/strcat/

strncat
http://www.cplusplus.com/reference/cstring/strncat/

Download

Source code at github
https://github.com/benbai123/C_Cplusplus_Practice/blob/master/C_StringProcessing/string_concat.c

C String: Copy String (Simple Note)


Simple Note

Code

#include <stdio.h>
#include <string.h>
/**
 * 
 * Tested with Dev-C++ 4.9.9.2
 *  
 * Practice of string copy and concat.
 * char * strcpy ( char * destination, const char * source );
 *         copy source to destination
 * char * strncpy ( char * destination, const char * source, size_t num );
 *         copy first n (the specified num) char
 *         from source to destination
 * memset ( void * ptr, int value, size_t num );
 *        Sets the first n (the specified num) bytes of the
 *          block of memory pointed by ptr to the specified value
 *        (interpreted as an unsigned char).
 * 
 */
int main () {
    // a char array without '\0'
    char chArr[4] = {'a', 'b', 'c', 'd'};
    char chArrTwo[6] = "mnopq";
    char chArrThree[6];
    char chArrFour[6];

    // copy chArr to chArrThree
    // will not add '\0' automatically
    strcpy(chArrThree, chArr);
    printf("chArrThree terminate with \\0? %s \n", (chArrThree[4] == '\0'? "true" : "false"));
    // output chArrThree, may contains wrong value since no \0
    printf("%s\n", chArrThree);


    // add \0 manually
    chArrThree[4] = '\0';
    // copy (replace) first Three char of chArrTwo to chArrThree
    strncpy(chArrThree, chArrTwo, 2);
    printf("chArrThree terminate with \\0? %s \n", (chArrThree[4] == '\0'? "true" : "false"));
    // output chArrThree correctly
    printf("%s\n", chArrThree);

    // use memset to preset all chars in chArrFour to \0
    memset(chArrFour, '\0', sizeof(chArrFour));
    // copy chArr to chArrFour
    strncpy(chArrFour, chArr, sizeof(chArr));
    // NOTE:
    // use strncpy will not clear all specified '\0' --> correct
    // use strcpy as below will clear all specified '\0' --> cause wron string
    // strcpy(chArrFour, chArr);
    printf("chArrFour terminate with \\0? %s \n", (chArrFour[4] == '\0'? "true" : "false"));
    // output chArrFour correctly
    printf("%s\n\n", chArrFour);

    system("PAUSE");
}


Result


References

strcpy
http://www.cplusplus.com/reference/cstring/strcpy/

strncpy
http://www.cplusplus.com/reference/cstring/strncpy/

memset
http://www.cplusplus.com/reference/cstring/memset/

Download

Source code at github
https://github.com/benbai123/C_Cplusplus_Practice/blob/master/C_StringProcessing/string_copy.c

Sunday, February 17, 2013

C String: Declare, Modify and Length (Simple Note)


Simple Note

Code

#include <stdio.h>
#include <string.h>

int main () {
    /**
     * declare, modify and length
     *
     */
    // declare string
    char* chPtr = "abcdefg";// will add '\0' at the tail automatically
    char chArr[] = "bbcdefg";
    char chArrTwo[] = {'c', 'b', 'c', 'd', 'e', 'f', 'g'}; // will not add '\0' automatically
    char chArrThree[] = {'d', 'b', 'c', 'd', 'e', 'f', 'g', '\0', '\0', '\0'};

    // output string
    printf("chPtr = %s\n", chPtr);
    printf("chArr = %s\n", chArr);
    printf("chArrTwo = %s\n", chArrTwo);
    printf("chArrThree = %s\n", chArrThree);

    // output length by sizeof
    // 4, the size of pointer
    printf ("\nLenbgh of char pointer = %d\n", sizeof(chPtr));
    // 8, the size of whole array
    // including a, b, c, d, e, f, g and '\0' (the terminate char added automatically)
    printf ("Length of char array = %d\n", sizeof(chArr));
    // 7, no terminate char
    printf ("Length of char array two = %d\n", sizeof(chArrTwo));
    // 10, including 3 terminate char
    printf ("Length of char array three = %d\n", sizeof(chArrThree));

    // output length by strlen
    // 7, only count the length before first '\0' or array length
    printf ("\nLenbgh of char pointer = %d\n", strlen(chPtr));
    printf ("Length of char array = %d\n", strlen(chArr));
    printf ("Length of char array two = %d\n", strlen(chArrTwo));
    printf ("Length of char array three = %d\n", strlen(chArrThree));

    // replace first char
    // cannot modify char points by a char pointer
    // this line below cause the runtime error
    // chPtr[0] = 'w';
    chArr[0] = 'x';
    chArrTwo[0] = 'y';
    chArrThree[0] = 'z';

    // output string again
    printf("\nchPtr = %s\n", chPtr);
    printf("chArr = %s\n", chArr);
    printf("chArrTwo = %s\n", chArrTwo);
    printf("chArrThree = %s\n\n", chArrThree);
    
    system("PAUSE");
}


Result



Reference

cplusplus
http://www.cplusplus.com/reference/cstring/strlen/

Thread at SF: Is it possible to modify a string of char in C?
http://stackoverflow.com/questions/1011455/is-it-possible-to-modify-a-string-of-char-in-c

Download

Code at github
https://github.com/benbai123/C_Cplusplus_Practice/blob/master/C_StringProcessing/string_declare_modify_and_length.c