WaBis

walter.bislins.ch

Datei: xTextControl: edit.js

Inhalt der Datei: javascript/xtc/src/edit.js
// xTextControl Demo: a simple texteditor for a textarea
// requires x.js, xtc.js
//
// Call WriteEditToolbarHTML( aTextFieldID, aPicDir ) to create the Toolbar.
//
// <aTextFieldID> is the ID of the textarea on which to apply the edit functions
// <aPicDir> is the relativ path to the directory with the toolbar button icons
//

// Url of a page that should be invoked with the help button
var CToolbarHelpPage = 'http://walter.bislins.ch/doku/xtc';

//----------------------------------------------------------

function w() { for (var i = 0; i < w.arguments.length; i++) document.write(w.arguments[i]); }
function wl() { for (var i = 0; i < wl.arguments.length; i++) document.write(wl.arguments[i]); document.writeln('');}

function UrlEncode(s) {
  var ss = s;
  ss = escape(ss);
  ss = ss.replace(/\//g,'%2F');
  ss = ss.replace(/\+/g,'%2B');
  ss = ss.replace(/\*/g,'%2A');
  ss = ss.replace(/@/g,'%40');
  ss = ss.replace(/%20/g,'+');
  return ss;
}

var ToolbarActivated = false;
var ShiftPressed = false;
var SavedText = '';
var SavedCursor = 0;

function OnEditKeyDown( aEvent, aTextFieldID ) {
  var ev = new xEvent(aEvent);
  var key = String.fromCharCode(ev.keyCode);
  if (ToolbarActivated) {
    if (key == '1') DoHeadline(aTextFieldID, 1);
    if (key == '2') DoHeadline(aTextFieldID, 2);
    if (key == '3') DoHeadline(aTextFieldID, 3);
    if (key == 'B') DoBold(aTextFieldID);
    if (key == 'I') DoItalic(aTextFieldID);
    if (key == 'W') DoLink(aTextFieldID);
    if (key == 'X') DoExtlink(aTextFieldID);
    if (key == 'E') DoMail(aTextFieldID);
    if (key == 'R') DoRedir(aTextFieldID);
    if (key == 'P') DoImage(aTextFieldID);
    if (key == 'M') DoMath(aTextFieldID);
    if (ev.keyCode == 189 || ev.keyCode == 109) DoHr(aTextFieldID);
    if (ev.keyCode == 190) DoBreak(aTextFieldID);
    if (key == 'L') DoUList(aTextFieldID);
    if (key == 'N') DoOList(aTextFieldID);
    if (key == 'Z') DoIndent(aTextFieldID);
    if (key == 'U') DoUnindent(aTextFieldID);
    if (key == 'V') DoInsertCB(aTextFieldID);
    if (key == 'T') DoTable(aTextFieldID);
    if (key == 'H') DoTableHead(aTextFieldID);
    if (key == 'C') DoTT(aTextFieldID);
    if (key == 'Q') DoQuot(aTextFieldID);
    if (key == 'A') Autoformat(aTextFieldID);
    if (ev.keyCode == 16) ShiftPressed = !ShiftPressed;
    // alert( 'keyCode = ' + ev.keyCode + '\nkey = ' + key );
    // ignore pressing of shift, control key
    if (ev.keyCode != 16 && ev.keyCode != 17) {
      ToolbarActivated = false;
      ShiftPressed = false;
      ShowKeyState( aTextFieldID );
    }
    return false;
  }
  // Ctrl-Z: save current cursor position and let text field do the undo
  if ((key == 'Z') && ev.ctrlKey && !ev.altKey && !ev.shiftKey ) {
    ResetCursorAfterUndo(aTextFieldID);
    return true;
  }
  // Crtl-W or Ctrl-Space for Wiki Edit Commands (prevents closing of window with Ctrl-W!)
  if ((key == 'W' || key == ' ') && ev.ctrlKey && !ev.altKey && !ev.shiftKey ) {
    ToolbarActivated = true;
    ShiftPressed = false;
    ShowKeyState(aTextFieldID);
    return false;
  }
  // Ctrl-Y: CutLines
  if ((key == 'Y') && ev.ctrlKey && !ev.altKey && !ev.shiftKey ) {
    CutLines(aTextFieldID);
    return false;
  }
  // Ctrl-DEL: DelWord
  if ((ev.keyCode == 46) && ev.ctrlKey && !ev.altKey && !ev.shiftKey ) {
    DelWord(aTextFieldID);
    return false;
  }
  // disable ESC to prevent accidental loss of text
  if (ev.keyCode == 27) {
    return false;
  }
  return true;
}

function ShowKeyState( aTextFieldID ) {
  var color = ToolbarActivated ? '#000000' : '#B4B4B4';
  xStyle( aTextFieldID+'Toolbar', 'borderColor', color);
}

//---------------------------------------------------------------
// Edit Helper Functions

function Trim( aText ) {
  var s = aText.replace( /[\t\n]/g, ' ' );
  s = s.replace( /^[ ]*(.*?)[ ]*$/, '$1' );
  return s;
}

function RTrim( aText ) {
  var s = aText.replace( /[\t\n]/g, ' ' );
  s = s.replace( /(.*?)[ ]*$/, '$1' );
  return s;
}

var CBlankPattern = /[ \t]/;
var CBlankOrNlPattern = /[ \t\n]/;
var CIBPattern = /[ \t\n\']/;
var CWordCharPattern = /[\w\d_äöüÄÖÜßçàáâèéêôûÁÀÂÉÈÊÔÛ]/;
var CNotWordCharPattern = /[^\w\d_äöüÄÖÜßçàáâèéêôûÁÀÂÉÈÊÔÛ \t\n]/;
var CUrlCharPattern = /[\w\d_+\-$@&\.!\*\"\'\(\),=;\/#\?:]/;

function IsBlank( aChar ) {
  return IsCharPattern( aChar, CBlankPattern );
}

function IsBlankOrNl( aChar ) {
  return IsCharPattern( aChar, CBlankOrNlPattern );
}

function IsCharPattern( aChar, aCharPattern ) {
  return aCharPattern.test(aChar);
}

function GetPatternStartPos( aCharPattern, aText, aPos ) {
  // finds also start of pattern at aPos-1
  // returns aPos if no pattern found
  var p = aPos - 1;
  while (p >= 0 && aCharPattern.test(aText.charAt(p))) p--;
  return p + 1;
}

function GetPatternEndPos( aCharPattern, aText, aPos ) {
  // returnes aPos if no pattern found at aPos
  var pos = aPos;
  var len = aText.length;
  while (pos < len && aCharPattern.test(aText.charAt(pos))) pos++;
  return pos;
}

function GetPatternPos( aCharPattern, aText, aPos ) {
  // if no pattern is found then { StartPos=aPos, EndPos=aPos } is returned
  var pos = { StartPos:0, EndPos:0 };
  pos.StartPos = GetPatternStartPos( aCharPattern, aText, aPos );
  pos.EndPos = GetPatternEndPos( aCharPattern, aText, aPos );
  return pos;
}

function IsEmptyLine( aLine ) {
  // returns true if aLine contains only blanks, tabs and NL or is empty
  return (aLine.replace( /[ \t\n]/g, '' ).length == 0);
}

function IsInEmptyLine( aText, aPos ) {
  // require( aPos >= 0 && aPos <= aText.length );
  var line = GetLinePos( aText, aPos );
  var s = aText.substring( line.StartPos, line.EndPos );
  return IsEmptyLine(s);
}

function GetLinePos( aText, aPos ) {
  // returns start and end position of line at aPos
  // EndPos is allways behind NL of the line at aPos
  var line = { StartPos:0, EndPos:0 };
  line.StartPos = GetLineStartPos( aText, aPos );
  line.EndPos = GetLineEndPos( aText, aPos );
  return line;
}

function SplitLines( aText ) {
  var text = aText;
  var len = text.length;
  if (len > 0 && text.charAt(len-1) == '\n') text = text.substring( 0, len-1 );
  return text.split( '\n' );
}

function JoinLines( aLines ) {
  return aLines.join( '\n' ) + '\n';
}

function GetLineStartPos( aText, aPos ) {
  // require( aPos >= 0 && aPos <= aText.length );
  return (aPos > 0) ? aText.lastIndexOf( '\n', aPos-1 ) + 1 : 0;
}

function GetLineLastPos( aText, aPos ) {
  // returns pos of last char of line (the NL, if exists)
  // require( aPos >= 0 && aPos <= aText.length );
  var nlPos = aText.indexOf( '\n', aPos );
  if (nlPos == -1) nlPos = aText.length;
  return nlPos;
}

function GetLineEndPos( aText, aPos ) {
  // returns end pos if line = start pos of next line
  // require( aPos >= 0 && aPos <= aText.length );
  var nlPos = aText.indexOf( '\n', aPos ) + 1;
  if (nlPos == 0) nlPos = aText.length;
  return nlPos;
}

function GetLineText( aText, aPos ) {
  // returns line inclusiv endling NL (if exists)
  var line = GetLinePos( aText, aPos );
  return aText.substring( line.StartPos, line.EndPos );
}

function GetTagContentStartPos( aText, aStartTag, aEndTag, aPos ) {
  var startTagPos = aText.lastIndexOf( aStartTag, aPos-aStartTag.length );
  if (startTagPos == -1) return -1;
  var nlPos = aText.lastIndexOf( '\n', aPos-1 );
  if (nlPos > startTagPos) return -1;
  var startTagContentPos = startTagPos + aStartTag.length;
  var endTagPos = aText.lastIndexOf( aEndTag, aPos-aEndTag.length );
  if (endTagPos == -1) return startTagContentPos;
  if (startTagPos < endTagPos) return -1;
  return startTagContentPos;
}

function GetTagContentEndPos( aText, aStartTag, aEndTag, aPos ) {
  var endTagPos = aText.indexOf( aEndTag, aPos );
  if (endTagPos == -1) return -1;
  var nlPos = aText.indexOf( '\n', aPos );
  if (nlPos >= 0 && nlPos < endTagPos) return -1;
  var startTagPos = aText.indexOf( aStartTag, aPos );
  if (startTagPos == -1) return endTagPos;
  if (startTagPos < endTagPos) return -1;
  return endTagPos;
}

function GetTagContentPos( aText, aStartTag, aEndTag, aSelStart, aSelEnd ) {
  // if aPos is not between aStartTag and aEndTag then
  // returns StartPos == EndPos == aSelStart
  var pos = { StartPos:aSelStart, EndPos:aSelStart };
  var startPos = GetTagContentStartPos( aText, aStartTag, aEndTag, aSelStart );
  var endPos = GetTagContentEndPos( aText, aStartTag, aEndTag, aSelEnd );
  if (startPos == -1 || endPos == -1) return pos;
  pos.StartPos = startPos;
  pos.EndPos = endPos;
  return pos;
}

function FindBlockStart( aText, aPos ) {
  // require( aPos >= 0 && aPos <= aText.length );
  // returns aText.length if no block is found
  var p = aPos;
  var len = aText.length;
  // find next not empty line to the right
  while (IsInEmptyLine(aText,p)) {
    p++;
    if (p >= len) return len;
  }
  // p is not in empty line, find first empty line to the left
  do {
    p = GetLineStartPos( aText, p );
    if (p <= 0) return 0;
    p--;
  }
  while (!IsInEmptyLine(aText,p));
  return p+1;
}

function FindBlockEnd( aText, aPos ) {
  // require( aPos >= 0 && aPos <= aText.length );
  // returns start pos of first empty line after block of not empty lines
  // returns 0 if no block is found
  var p = aPos;
  var len = aText.length;
  // find first not empty line to the left
  while (p >= 0 && IsInEmptyLine(aText,p)) {
    p--;
  }
  if (p < 0) return 0;
  // p is not in empty line, find first empty line to the right
  do {
    p = GetLineEndPos( aText, p );
    if (p >= len) return len;
  }
  while (!IsInEmptyLine(aText,p));
  return p;
}

function FindBlockStartTag( aText, aTag, aPos ) {
  var p = aPos;
  while (p >= 0) {
    p = GetLineStartPos( aText, p );
    var line = RTrim(GetLineText( aText, p ));
    if (IsEmptyLine(line)) return -1;
    if (line == aTag) return p;
    p--;
  }
  return -1;
}

function FindBlockEndTag( aText, aTag, aPos ) {
  var p = aPos;
  var len = aText.length;
  while (p <= len) {
    p = GetLineLastPos( aText, p );
    var line = RTrim(GetLineText( aText, p ));
    if (IsEmptyLine(line)) return -1;
    if (line == aTag) return GetLineStartPos( aText, p );
    p++;
  }
  return -1;
}

function ExpandSelectionToPattern( aTextControl, aCharPattern ) {
  var pos = GetPatternPos( aCharPattern, aTextControl.Text, aTextControl.SelStart );
  if (pos.StartPos < pos.EndPos) {
    aTextControl.SetSelectionRange( pos.StartPos, pos.EndPos, false );
  }
}


function ExpandSelectionToLines( aTextControl ) {
  var text = aTextControl.Text;
  var startPos = GetLineStartPos( text, aTextControl.SelStart );
  // if selection not empty and endPos is on start of line, do not select this line
  var endPos = GetLineStartPos( text, aTextControl.SelEnd );
  if (aTextControl.SelStart == aTextControl.SelEnd || endPos != aTextControl.SelEnd) {
    endPos = GetLineEndPos( text, aTextControl.SelEnd );
  }
  aTextControl.SetSelectionRange( startPos, endPos, false );
}

function ExpandSelectionToBlocks( aTextControl ) {
  // returns false, if selection is outside any block
  var text = aTextControl.Text;
  var blockStartPos = FindBlockStart( text, aTextControl.SelStart );
  // if selection is not empty then adjust end pos to ensure only full selected blocks are returned
  var selEndPos = aTextControl.SelEnd;
  if (selEndPos > aTextControl.SelStart) selEndPos--;
  var blockEndPos = FindBlockEnd( text, selEndPos );
  // if no blocks are found
  if (blockStartPos >= blockEndPos) return false;
  aTextControl.SetSelectionRange( blockStartPos, blockEndPos, false );
  return true;
}

//---------------------------------------------------------------
// Edit Functions

function ResetCursorAfterUndo(aTextFieldID) {
  // save text of text field and let the undo function do his work
  // after some time check the difference and set the cursor back to the start of the change
  // or the last saved cursor position, if no changes are found
  var tc = new xTextControl(xGet(aTextFieldID));
  SavedText = tc.Text;
  SavedCursor = tc.SelStart;
  setTimeout( function(){ DoResetCursor(aTextFieldID); }, 100 );
}

function DoResetCursor(aTextFieldID) {
  var pos;
  var tc = new xTextControl(xGet(aTextFieldID));
  if (tc.Text == SavedText) {
    pos = SavedCursor;
  } else {
    pos = GetPosOfFirstDiff( tc.Text, SavedText );
  }
  tc.SetCaretPos( pos );
}

function GetPosOfFirstDiff( t1, t2 ) {
  var pos = 0;
  var l1 = t1.length;
  var l2 = t2.length;
  while (pos < l1 && pos < l2) {
    if (t1.charAt(pos) != t2.charAt(pos)) return pos;
    pos++;
  }
  return pos;
}

function SelectPattern( aTextFieldID, aCharPattern ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  ExpandSelectionToPattern( tc, aCharPattern );
  tc.UpdateControlSelection();
}

function SelectLines( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  ExpandSelectionToLines( tc );
  tc.UpdateControlSelection();
}

function SelectBlock( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  if (ExpandSelectionToBlocks(tc)) {
    tc.UpdateControlSelection();
  }
}

function ToggleBlockTags( aTextFieldID, aStartTag, aText, aEndTag ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  // check, if tags allready exists
  var tagsFound = false;
  var emptyBlock = false;
  var blockStartTagPos = FindBlockStartTag( text, aStartTag, tc.SelStart );
  var blockEndTagPos = -1;
  if (blockStartTagPos >= 0) {
    blockEndTagPos = FindBlockEndTag( text, aEndTag, tc.SelEnd );
    if (blockEndTagPos >= 0) tagsFound = true;
  }
  if (!tagsFound) {
    if (ExpandSelectionToBlocks(tc)) {
      var firstLine = RTrim(GetLineText( text, tc.SelStart ));
      var lastLine = RTrim(GetLineText( text, tc.SelEnd-1 ));
      if (firstLine == aStartTag && lastLine == aEndTag) {
        blockStartTagPos = tc.SelStart;
        blockEndTagPos = GetLineStartPos( text, tc.SelEnd-1 );
        tagsFound = true;
      }
    }
    else {
      // selection is not inside a block, expand it to whole empty lines
      emptyBlock = true;
      var lineStartPos = GetLineStartPos( text, tc.SelStart );
      var lineEndPos = GetLineEndPos( text, tc.SelEnd );
      if (lineEndPos > text.length) lineEndPos = text.length;
      tc.SetSelectionRange( lineStartPos, lineEndPos, false );
    }
  }
  if (tagsFound) {
    // tags allready exists, remove them
    var keepStartPos = GetLineEndPos( text, blockStartTagPos );
    var keepText = text.substring( keepStartPos, blockEndTagPos );
    var selEndPos = GetLineEndPos( text, blockEndTagPos );
    tc.ChangeSelection( blockStartTagPos, selEndPos, keepText, true );
    return;
  }
  // no such tags in current blocks
  // block must have a ending '\n'
  var newText = tc.SelText
  var newSelStart = tc.SelStart;
  var newSelEnd = newText.length;
  if (newText.length > 0 && newText.charAt(newText.length-1) != '\n') {
    newText += '\n';
    newSelEnd++;
  }
  // insert tags and select block
  if (emptyBlock) {
    // insert a blank block
    newText = aText + '\n';
    newSelEnd = newText.length;
  }
  newText = aStartTag + '\n' + newText + aEndTag + '\n';
  newSelStart += aStartTag.length + 1;
  // insert blank lines around block
  if (tc.SelStart > 0) {
    if (!IsInEmptyLine( text, tc.SelStart-1 )) {
      newText = '\n' + newText;
      newSelStart++;
    }
  }
  if (tc.SelEnd <= text.length) {
    if (!IsInEmptyLine( text, tc.SelEnd )) {
      newText += '\n';
    }
  }
  newSelEnd += newSelStart;
  tc.ChangeSelection( tc.SelStart, tc.SelEnd, newText, false );
  tc.SetSelectionRange( newSelStart, newSelEnd, true );
}

function InsertBlock( aTextFieldID, aStartTag, aText, aEndTag, bNlOnTop ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  var newSelStart = GetLineStartPos( text, tc.SelStart );
  var selStart = newSelStart;
  var selEnd = newSelStart;
  var newText = aStartTag + aText + aEndTag + '\n';
  newSelStart += aStartTag.length;
  // insert blank lines
  if (bNlOnTop && selStart > 0) {
    if (!IsInEmptyLine( text, selStart-1 )) {
      newText = '\n' + newText;
      newSelStart++;
    }
  }
  if (selEnd <= text.length) {
    if (!IsInEmptyLine( text, selEnd )) {
      newText += '\n';
    }
  }
  var newSelEnd = newSelStart + aText.length;
  tc.ChangeSelection( selStart, selEnd, newText, false );
  tc.SetSelectionRange( newSelStart, newSelEnd, true );
}

function ToggleLinkTags( aTextFieldID, aStartTag, aLink, aSep, aText, aEndTag, aCharPattern ) {
  if (aCharPattern == '') aCharPattern = CWordCharPattern;
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  // check if selection is inside existing tags, but not if starttag = endtag and selection is not empty
  var tagContent = GetTagContentPos( text, aStartTag, aEndTag, tc.SelStart, tc.SelEnd );
  if (aStartTag == aEndTag) {
    if (tc.SelStart == tc.SelEnd) {
      var patSel = GetPatternPos( aCharPattern, text, tc.SelStart );
      if (patSel.StartPos < patSel.EndPos) {
        tc.SetSelectionRange( patSel.StartPos, patSel.EndPos, false );
      }
    }
    if (tc.SelStart < tc.SelEnd && (tc.SelStart != tagContent.StartPos || tc.SelEnd != tagContent.EndPos)) {
      // not my tags
      tagContent.EndPos = tagContent.StartPos = tc.SelStart;
    }
  }
  if (tagContent.StartPos == tagContent.EndPos) {
    // not in tag
    if (tc.SelStart == tc.SelEnd) {
      // nothing selected, check if pattern to select is nearby
      var patSel = GetPatternPos( aCharPattern, text, tc.SelStart );
      if (patSel.StartPos == patSel.EndPos) {
        // no pattern to select, so insert tags and aLink
        var newText = aStartTag + aLink + aEndTag;
        tc.ChangeSelection( tc.SelStart, tc.SelEnd, newText, false );
        var newSelStart = tc.SelStart + aStartTag.length;
        var newSelEnd = tc.SelEnd - aEndTag.length;
        tc.SetSelectionRange( newSelStart, newSelEnd, true );
        return;
      }
      // pattern to select found, select it
      tc.SetSelectionRange( patSel.StartPos, patSel.EndPos, false );
    }
    // pattern selected, so insert tags
    // leerzeichen am Ende der selektion ausserhalb des End-Tags platzieren!
    var selStart = tc.SelStart;
    var selEnd = tc.SelEnd;
    while (selEnd > selStart && IsBlankOrNl(text.charAt(selEnd-1))) selEnd--;
    if (selEnd <= selStart) selEnd = tc.SelEnd;
    // tags einfügen
    var newText = aStartTag + text.substring( selStart, selEnd ) + aEndTag;
    tc.ChangeSelection( selStart, selEnd, newText, false );
    selStart = tc.SelStart + aStartTag.length;
    selEnd = tc.SelEnd - aEndTag.length;
    tc.SetSelectionRange( selStart, selEnd, true );
    return;
  }
  // selection is inside existing tag, check if aSep is inside tags
  var sepPos = -1;
  if (aSep != '') {
    sepPos = text.indexOf( aSep, tagContent.StartPos );
    if (sepPos >= tagContent.EndPos) sepPos = -1;
  }
  var newText = '';
  if (sepPos >= 0) {
    // aSep found between tags, remove tags and keep text on selected side of aSep
    if (tc.SelStart <= sepPos) {
      // keep left side of aSep
      newText = text.substring( tagContent.StartPos, sepPos );
    }
    else {
      // keep right side of aSep
      newText = text.substring( sepPos+aSep.length, tagContent.EndPos );
    }
    var selStart = tagContent.StartPos - aStartTag.length;
    var selEnd = tagContent.EndPos + aEndTag.length;
    tc.ChangeSelection( selStart, selEnd, newText, true );
    return;
  }
  // selection inside existing tags but no separator found
  if (aSep == '') {
    // remove tags and select contents
    var newText = text.substring( tagContent.StartPos, tagContent.EndPos );
    var selStart = tagContent.StartPos - aStartTag.length;
    var selEnd = tagContent.EndPos + aEndTag.length;
    tc.ChangeSelection( selStart, selEnd, newText, true );
    return;
  }
  // insert separator and copy and select existing content
  if (aText != '') {
    newText = aSep + aText;
  } else {
    newText = aSep + text.substring( tagContent.StartPos, tagContent.EndPos );
  }
  var selStart = tagContent.EndPos;
  var selEnd = selStart;
  tc.ChangeSelection( selStart, selEnd, newText, false );
  selStart = tc.SelStart + aSep.length;
  selEnd = tc.SelEnd;
  tc.SetSelectionRange( selStart, selEnd, true );
}

var CTagTypeItalic = 0;
var CTagTypeBold   = 1;

function ToggleIBTags( aTextFieldID, aTagType ) {
  // aTagType = CTagTypeItalic | CTagTypeBold
  var ITag = '\'\'';
  var BTag = '\'\'\'';
  var IBTag = ITag + BTag;
  var currentTag = (aTagType == CTagTypeItalic) ? ITag : BTag;
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  // reduce selection to ensure that tags are outside
  if (tc.SelStart < tc.SelEnd) {
    var startPos = tc.SelStart;
    var endPos = tc.SelEnd;
    while (endPos > startPos && IsCharPattern(text.charAt(endPos-1),CIBPattern)) endPos--;
    while (startPos < endPos && IsCharPattern(text.charAt(startPos),CIBPattern)) startPos++;
    if (startPos < endPos ) {
      tc.SetSelectionRange( startPos, endPos, false );
    }
  }
  // check if selection is inside existing tags, but not if starttag = endtag and selection is not empty
  var tagContentIB = GetTagContentPos( text, IBTag, IBTag, tc.SelStart, tc.SelEnd );
  var tagContentB = GetTagContentPos( text, BTag, BTag, tc.SelStart, tc.SelEnd );
  var tagContentI = GetTagContentPos( text, ITag, ITag, tc.SelStart, tc.SelEnd );
  var isIB = (tagContentIB.StartPos < tagContentIB.EndPos);
  var isB = (tagContentB.StartPos < tagContentB.EndPos);
  var isI = (tagContentI.StartPos < tagContentI.EndPos);
  if (!isIB && isB && isI) {
    // only the nearer tag is the relevant one
    if (tagContentB.StartPos >= tagContentI.StartPos && tagContentB.EndPos <= tagContentI.EndPos) {
      isI = false;
    } else {
      isB = false;
    }
  }
  if (!isIB && isB) isI = false;
  if (tc.SelStart == tc.SelEnd) {
    ExpandSelectionToPattern( tc, CWordCharPattern )
  }
  var isInTag = false;
  var cStartPos = 0;
  var cEndPos = 0;
  if (tc.SelStart < tc.SelEnd) {
    // somthing is selected
    if (isIB && tc.SelStart == tagContentIB.StartPos && tc.SelEnd == tagContentIB.EndPos) isInTag = true;
    if (aTagType == CTagTypeItalic) {
      if (isI && tc.SelStart == tagContentI.StartPos && tc.SelEnd == tagContentI.EndPos) {
        isInTag = true;
        cStartPos = tagContentI.StartPos;
        cEndPos = tagContentI.EndPos;
      }
    } else {
      if (isB && tc.SelStart == tagContentB.StartPos && tc.SelEnd == tagContentB.EndPos) {
        isInTag = true;
        cStartPos = tagContentB.StartPos;
        cEndPos = tagContentB.EndPos;
      }
    }
  }
  if (!isInTag) {
    // not in tag
    if (tc.SelStart == tc.SelEnd) {
      // nothing selected, so insert template
      var newText = currentTag + 'Text' + currentTag;
      tc.ChangeSelection( tc.SelStart, tc.SelEnd, newText, false );
      var selStart = tc.SelStart + currentTag.length;
      var selEnd = selStart + 4;
      tc.SetSelectionRange( selStart, selEnd, true );
      return;
    }
    // pattern selected, so insert tags
    // leerzeichen am Ende der selektion ausserhalb des End-Tags platzieren!
    var selStart = tc.SelStart;
    var selEnd = tc.SelEnd;
    while (selEnd > tc.SelStart && IsBlankOrNl(text.charAt(selEnd-1))) selEnd--;
    if (selEnd <= selStart) selEnd = tc.SelEnd;
    // tags einfügen
    var newText = currentTag + text.substring( selStart, selEnd ) + currentTag;
    tc.ChangeSelection( selStart, selEnd, newText, false );
    selStart = tc.SelStart + currentTag.length;
    selEnd = tc.SelEnd - currentTag.length;
    tc.SetSelectionRange( selStart, selEnd, true );
    return;
  }
  // selection is inside existing tag, so remove tags and select contents
  var newText = text.substring( cStartPos, cEndPos );
  var selStart = cStartPos - currentTag.length;
  var selEnd = cEndPos + currentTag.length;
  tc.ChangeSelection( selStart, selEnd, newText, true );
}

function ToggleInlineTags( aTextFieldID, aStartTag, aDefaultText, aEndTag ) {
  ToggleLinkTags( aTextFieldID, aStartTag, aDefaultText, '', '', aEndTag, CWordCharPattern );
}

function InsertText( aTextFieldID, aStr ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  var selStart = tc.SelStart;
  var selEnd = tc.SelEnd;
  if (selStart < selEnd) {
    // selektion trimmen, sodass nur ganze Worte markiert sind
    while (selEnd > selStart && IsBlankOrNl(text.charAt(selEnd-1))) selEnd--;
    if (selEnd <= selStart) selEnd = tc.SelEnd;
  }
  tc.ChangeSelection( selStart, selEnd, aStr, true );
}

function MovePrevLine( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  var cPos = tc.SelStart;
  var nPos = GetLineStartPos( text, cPos );
  if (nPos > 0) nPos = GetLineStartPos( text, nPos-1 );
  tc.SetCaretPos( nPos );
}

function DelWord( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  if (tc.SelStart < tc.SelEnd) {
    // if selection is not empty delete selection
    tc.ChangeSelectionText( '', true );
    return;
  }
  var text = tc.Text;
  if (tc.SelStart == text.length) return;
  var c = text.charAt( tc.SelStart );
  var selEnd = tc.SelEnd;
  if (c == '\n') {
    // delete end of line
    selEnd++;
  }
  else if (IsCharPattern( c, CWordCharPattern )) {
    // delete word and trailing blanks
    selEnd = GetPatternEndPos( CWordCharPattern, text, selEnd );
    if (selEnd < text.length && IsCharPattern(text.charAt(selEnd),CBlankPattern)) {
      // find end of blanks
      selEnd = GetPatternEndPos( CBlankPattern, text, selEnd );
    }
  }
  else if (IsCharPattern( c, CBlankPattern )) {
    // delete blanks
    selEnd = GetPatternEndPos( CBlankPattern, text, selEnd );
  }
  else {
    // delete special chars and trailing blanks
    selEnd = GetPatternEndPos( CNotWordCharPattern, text, selEnd );
    if (selEnd < text.length && IsCharPattern(text.charAt(selEnd),CBlankPattern)) {
      // find end of blanks
      selEnd = GetPatternEndPos( CBlankPattern, text, selEnd );
    }
  }
  tc.ChangeSelection( tc.SelStart, selEnd, '', true );
}

function CutLines( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  ExpandSelectionToLines( tc );
  var isAtEnd = (tc.Text.length == tc.SelEnd);
  tc.ChangeSelection( tc.SelStart, tc.SelEnd, '', true );
  if (isAtEnd) MovePrevLine(aTextFieldID);
}

function MakeHeader( aTextFieldID, aLevel, sampleText ) {
  var s = '=';
  for (var i = 0; i < aLevel; i++) s += '=';
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  var line = GetLinePos( text, tc.SelStart );
  var header = RTrim( text.substring( line.StartPos, line.EndPos ) );
  // check Wiki header level
  var hl = header.replace(/^(=*).*/, '$1').length - 1;
  if (header == '') {
    header = sampleText;
  } else {
    // strip Wiki header code
    header = header.replace( /^[= ]*(.*?)[= ]*$/, '$1' );
  }
  if (hl == aLevel) {
    // if header is allready this level make a paragraph
    var newText = header + '\n';
    tc.ChangeSelection( line.StartPos, line.EndPos, newText, true );
    return;
  }
  // make header
  var newText = s + ' ' + header + ' ' + s + '\n';
  var newStart = line.StartPos + aLevel + 2;
  var newEnd = newStart + header.length;
  // add empty lines
  if (line.StartPos > 0 && !IsInEmptyLine(text,line.StartPos-1)) {
    newText = '\n' + newText;
    newStart++; newEnd++;
  }
  if (line.EndPos >= text.length || !IsInEmptyLine(text,line.EndPos)) {
    newText += '\n';
  }
  tc.ChangeSelection( line.StartPos, line.EndPos, newText, false );
  tc.SetSelectionRange( newStart, newEnd, true );
}

function Indent( aTextFieldID, aChar ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  // check cursor on empty line
  if (tc.SelStart == tc.SelEnd && IsInEmptyLine(text,tc.SelStart)) {
    var selStart = GetLineStartPos( text, tc.SelStart );
    var selEnd = GetLineLastPos( text, tc.SelEnd );
    var newText = aChar + ' text';
    tc.ChangeSelection( selStart, selEnd, newText, false );
    selEnd = tc.SelStart + newText.length;
    selStart = tc.SelStart + aChar.length + 1;
    tc.SetSelectionRange( selStart, selEnd, true );
    return;
  }
  ExpandSelectionToLines( tc );
  var lines = SplitLines( tc.SelText );
  var replStr = '$1' + aChar + ' ';
  for (i = 0; i < lines.length; i++) {
    if (!IsEmptyLine(lines[i])) {
      lines[i] = lines[i].replace( /(^[\*#:]*)[ \t]*/, replStr );
    }
  }
  var newText = JoinLines( lines );
  tc.ChangeSelectionText( newText, true );
}

function Unindent( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  ExpandSelectionToLines( tc );
  var lines = SplitLines( tc.SelText );
  for (i = 0; i < lines.length; i++) {
    var line  = lines[i].replace( /(^[\*#:]*?)[\*#:]([^\*#:])/, '$1$2' );
    lines[i] = line.replace( /(^[ ]*)/, '' );
  }
  var newText = JoinLines( lines );
  tc.ChangeSelectionText( newText, true );
}

function ParseTextTable( aText ) {
  var s = aText.replace( /\"\"/g, '\001' );
  var l = s.split( '"' );
  for (var i = 1; i < l.length; i += 2) {
    var s = l[i].replace( /;/g, '\002' );
    l[i] = s.replace( /\n/g, '\003' );
  }
  s = l.join('');
  var rows = s.split( '\n' );
  var tab = new Array();
  for (var row = 0; row < rows.length; row++ ) {
    s = rows[row];
    if (!IsEmptyLine(s)) {
    l = s.split(';');
      for (var col = 0; col < l.length; col++ ) {
        s = Trim(l[col]);
        s = s.replace( /\003/g, '\n' );
        s = s.replace( /\002/g, ';' );
        s = s.replace( /\001/g, '"' );
        l[col] = s;
      }
      tab.push( l );
    }
  }
  return tab;
}

function DoTable( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  // check cursor on empty line
  if (!ExpandSelectionToBlocks(tc)) {
    InsertBlock( aTextFieldID, '{| ', 'grid', '\n! \n! \n|-\n| \n| \n|}', true );
    return;
  }
  // parse table
  var tab = ParseTextTable( tc.SelText );
  // make wiki table
  var s = '{| grid\n';
  for (var i = 0; i < tab.length; i++) {
    var row = tab[i];
    if (i > 0) s += '|-\n';
    for (var j = 0; j < row.length; j++) {
      s += '| ' + row[j] + '\n';
    }
  }
  s += '|}\n';
  tc.ChangeSelectionText( s, true );
}

function DoTableHead( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  var text = tc.Text;
  // check cursor on empty line
  if (tc.SelStart == tc.SelEnd && IsInEmptyLine(text,tc.SelStart)) return;
  ExpandSelectionToLines( tc );
  var lines = SplitLines( tc.SelText );
  for (var i = 0; i < lines.length; i++) {
    var s = lines[i];
    if (s.length > 0) {
      if (s.charAt(0) == '|') {
        if (s.length > 1 && s.charAt(1) != '-' && s.charAt(1) != '}') {
          s = '!' + s.substring(1);
          lines[i] = s;
        }
      }
      else if (s.charAt(0) == '!') {
        s = '|' + s.substring(1);
        lines[i] = s;
      }
    }
  }
  var newText = JoinLines( lines );
  tc.ChangeSelectionText( newText, true );
}

function Autoformat( aTextFieldID ) {
  var tc = new xTextControl(xGet(aTextFieldID));
  ExpandSelectionToLines( tc );
  var txt = '\n' + tc.SelText;
  txt = txt.replace(/ß/g, 'ss');
  // remove trailing blanks
  txt = txt.replace(/\t/g, ' ');
  txt = txt.replace(/[ ]+\n/g, '\n');
  // remove hyphenations (Trennzeichen)
  txt = txt.replace(/([a-zöäü])\-([a-zöäü])/g, '$1$2');
  // make lists
  txt = txt.replace(/\n *[^a-zA-Z0-9äöüÄÖÜ \'\"\n\{\|=#;\[«<(\/%]+? */g, '\n* ');
  txt = txt.replace(/\n *\d+\. *([^\n])/g, '\n# $1');
  // insert blank line before list
  txt = txt.replace(/(\n[\*#] [^\n])/g, '\n$1');
  // remove returns in paragraphs
  txt = txt.replace(/([^\n])\n([^\n])/g, '$1 $2');
  txt = txt.replace(/ \/\/\/ /g, '<br>\n');
  // remove blank lines in lists
  txt = txt.replace(/\n([\*#])/g, '$1');
  txt = txt.replace(/(\n[^\*#\n].+\n)([\*#])/g, '$1\n$2');
  // make separated lines without ., <, ' and : to header
  txt = txt.replace(/(\n)([^\*=\n\.:\<\']+)(\n)/g, '$1== $2 ==$3');
  txt = txt.replace(/<br>/g, ' ///');
  // remove inserted nl at begin
  txt = txt.substring(1);
  tc.ChangeSelectionText( txt, true );
}

// -------------------------------------------------------------------------------------

function DoBlockFormat( aSelectControl, aTextFieldID ) {
  var wert = aSelectControl.options[aSelectControl.options.selectedIndex].value;
  if (wert == 'intro')    ToggleBlockTags( aTextFieldID, '<intro>', 'Text', '</intro>' );
  if (wert == 'bigdir')   ToggleBlockTags( aTextFieldID, '{{bigdir}}', '* [[]]', '{{end bigdir}}' );
  if (wert == 'poem')     ToggleBlockTags( aTextFieldID, '<poem>', 'Text', '</poem>' );
  if (wert == 'comment')  ToggleBlockTags( aTextFieldID, '<comment>', 'Text', '</comment>' );
  if (wert == 'code')     ToggleBlockTags( aTextFieldID, '<code>', 'Text', '</code>' );
  if (wert == 'hidden')   ToggleBlockTags( aTextFieldID, '<hidden>', 'Text', '</hidden>' );
  if (wert == 'html')     ToggleBlockTags( aTextFieldID, '<html>', 'Text', '</html>' );
  if (wert == 'div')      ToggleBlockTags( aTextFieldID, '{{div|$style}}', 'Text', '{{end div}}' );
  if (wert == 'data')     ToggleBlockTags( aTextFieldID, '{{data}}', 'Text', '{{end data}}' );
  if (wert == 'keywords') InsertBlock( aTextFieldID, '#KEYWORDS ', 'Keyword1, Keyword2, ...', '', false );
  if (wert == 'include')  InsertBlock( aTextFieldID, '{{include|', 'Page#Part', '}}', false );
  if (wert == 'style')    InsertBlock( aTextFieldID, '{{style}}\n#wiki .', 'class', ' {  }\n{{end style}}', true );
  if (wert == 'script')   InsertBlock( aTextFieldID, '{{script}}\n', 'javascript();', '\n{{end script}}', true );
  if (wert == 'macrodef') InsertBlock( aTextFieldID, '{{*', 'Name', '|Text*}}', true );
  if (wert == 'wscript')  InsertBlock( aTextFieldID, '<wscript>\n', 'WikiScript', '\n</wscript>', true );
  aSelectControl.options.selectedIndex = 0;
}

function DoBold(id)         { ToggleIBTags( id, CTagTypeBold ); }
function DoItalic(id)       { ToggleIBTags( id, CTagTypeItalic ); }
function DoQuot(id)         { ToggleInlineTags( id, '<<', 'Text', '>>' ); }
function DoTT(id)           { ToggleInlineTags( id, '<<<', 'Text', '>>>' ); }
function DoRedir(id)        { ToggleInlineTags( id, '#REDIRECT [[', 'Link', ']]' ); }
function DoImage(id)        { InsertBlock( id, '[[', 'Bild:picture.jpg', '|zoom|180px|right|framed|Text]]', false ); }
function DoMath(id)         { ToggleInlineTags( id, '{{math|', 'x', '}}' ); }
function DoNowiki(id)       { ToggleInlineTags( id, '<nowiki>', 'Text', '</nowiki>' ); }
function DoLink(id)         { ToggleLinkTags( id, '[[', 'Link', '|', '', ']]', CWordCharPattern ); }
function DoExtlink(id)      { ToggleLinkTags( id, '[', 'http://www.domain.ch/', ' ', 'Website', ']', CUrlCharPattern ); }
function DoMail(id)         { ToggleLinkTags( id, '[mailto:', 'name@domain.com', ' ', 'Name', ']', CUrlCharPattern ); }
function DoHeadline(id,lvl) { MakeHeader( id, lvl, 'Headline' ); }
function DoBreak(id)        { InsertBlock( id, '{{break}}', '', '', true ); }
function DoHr(id)           { InsertBlock( id, '----', '', '', true ); }
function DoInsertCB(id)     { InsertBlock( id, '', GetFirstClipboardEntry(), '', false ); }
function DoUList(id)        { Indent( id, '*' ); }
function DoOList(id)        { Indent( id, '#' ); }
function DoIndent(id)       { Indent( id, ':' ); }
function DoUnindent(id)     { Unindent( id ); }

function GetFirstClipboardEntry() {
  if (WIKI_CLIPBOARD.length == 0) return '';
  return WIKI_CLIPBOARD[0];
}

function DoHelp(aTextFieldID) {
  window.open( CToolbarHelpPage, "_blank" );
}

// -------------------------------------------------------------------------------------

function WriteEditToolbarHTML( aTextFieldID, aPicDir ) {
  var id = aTextFieldID;
  w('<table id="' + id + 'Toolbar" style="width:100%;background-color:#EEEEEE;border:2px solid #B4B4B4;border-width:2px 1px;margin:4px 0 0 0;"><tr>');
  w('<td style="vertical-align:top;padding:0;white-space:nowrap;">');
  w('<img src="'+aPicDir+'zbl.gif" width="4" height="26" alt="">');
  w('<img src="'+aPicDir+'zh1.gif" width="21" height="26" onclick="DoHeadline(\''+id+'\',1)" alt="Header Level 1 [Crtl-Space]+[1]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zh2.gif" width="21" height="26" onclick="DoHeadline(\''+id+'\',2)" alt="Header Level 2 [Crtl-Space]+[2]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zh3.gif" width="21" height="26" onclick="DoHeadline(\''+id+'\',3)" alt="Header Level 3 [Crtl-Space]+[3]">');
  w('<img src="'+aPicDir+'zbr.gif" width="2" height="26" alt="">');
  w('<img src="'+aPicDir+'zbl.gif" width="4" height="26" alt="">');
  w('<img src="'+aPicDir+'zbold.gif" width="21" height="26" onclick="DoBold(\''+id+'\')" alt="Bold [Crtl-Space]+[B]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zitalic.gif" width="21" height="26" onclick="DoItalic(\''+id+'\')" alt="Italic [Crtl-Space]+[I]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zq.gif" width="21" height="26" onclick="DoQuot(\''+id+'\')" alt="Quot [Crtl-Space]+[Q]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'ztt.gif" width="21" height="26" onclick="DoTT(\''+id+'\')" alt="Teletype [Crtl-Space]+[C]">');
  w('<img src="'+aPicDir+'zbr.gif" width="2" height="26" alt="">');
  w('<img src="'+aPicDir+'zbl.gif" width="4" height="26" alt="">');
  w('<img src="'+aPicDir+'zul.gif" width="21" height="26" onclick="DoUList(\''+id+'\')" alt="Unordered List [Crtl-Space]+[L]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zol.gif" width="21" height="26" onclick="DoOList(\''+id+'\')" alt="Ordered List [Crtl-Space]+[N]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zin.gif" width="21" height="26" onclick="DoIndent(\''+id+'\')" alt="Indent [Crtl-Space]+[Z]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zuin.gif" width="21" height="26" onclick="DoUnindent(\''+id+'\')" alt="Unindent [Crtl-Space]+[U]">');
  w('<img src="'+aPicDir+'zbr.gif" width="2" height="26" alt="">');
  w('<img src="'+aPicDir+'zbl.gif" width="4" height="26" alt="">');
  w('<img src="'+aPicDir+'zwlink.gif" width="21" height="26" onclick="DoLink(\''+id+'\')" alt="Wiki Link [Crtl-Space]+[W]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zlink.gif" width="21" height="26" onclick="DoExtlink(\''+id+'\')" alt="Web Link [Crtl-Space]+[X]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zmail.gif" width="21" height="26" onclick="DoMail(\''+id+'\')" alt="Email [Crtl-Space]+[E]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zredir.gif" width="21" height="26" onclick="DoRedir(\''+id+'\')" alt="Redirect [Crtl-Space]+[R]">');
  w('<img src="'+aPicDir+'zbr.gif" width="2" height="26" alt="">');
  w('<img src="'+aPicDir+'zbl.gif" width="4" height="26" alt="">');
  w('<img src="'+aPicDir+'zpic.gif" width="21" height="26" onclick="DoImage(\''+id+'\')" alt="Image [Crtl-Space]+[P]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zfx.gif" width="21" height="26" onclick="DoMath(\''+id+'\')" alt="Math-Format [Crtl-Space]+[M]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'ztab.gif" width="21" height="26" onclick="DoTable(\''+id+'\')" alt="Create Table from Text [Crtl-Space]+[T]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'ztabh.gif" width="21" height="26" onclick="DoTableHead(\''+id+'\')" alt="Toggle Table Head [Crtl-Space]+[H]">');
  w('<img src="'+aPicDir+'zbr.gif" width="2" height="26" alt="">');
  w('<img src="'+aPicDir+'zbl.gif" width="4" height="26" alt="">');
  w('<img src="'+aPicDir+'znowiki.gif" width="21" height="26" onclick="DoNowiki(\''+id+'\')" alt="nowiki">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zhr.gif" width="21" height="26" onclick="DoHr(\''+id+'\')" alt="Line [Crtl-Space]+[-]">');
  w('<img src="'+aPicDir+'zb.gif" width="1" height="26" alt="">');
  w('<img src="'+aPicDir+'zbreak.gif" width="21" height="26" onclick="DoBreak(\''+id+'\')" alt="Break [Crtl-Space]+[.]">');
  w('<img src="'+aPicDir+'zbr.gif" width="2" height="26" alt="">');
  w('<img src="'+aPicDir+'zbl.gif" width="4" height="26" alt="">');
  w('<img src="'+aPicDir+'zhelp.gif" width="21" height="26" onclick="DoHelp(\''+id+'\')" alt="Help">');
  w('<img src="'+aPicDir+'zbr.gif" width="2" height="26" alt="">');

  w('</td><td style="width:100%;vertical-align:top;padding:2px 0 0 3px;">');
  wl('<select size="1" name="BlockFunctions" onchange="DoBlockFormat(this,\''+id+'\')">');
  wl('<option value="-" selected="selected">Block-Format</option>');
  wl('<option value="intro">* Intro</option>');
  wl('<option value="bigdir">* Verzeichnis</option>');
  wl('<option value="poem">* Poem</option>');
  wl('<option value="code">* Code</option>');
  wl('<option value="div">* Div</option>');
  wl('<option value="data">* Data</option>');
  wl('<option value="comment">* Kommentar</option>');
  wl('<option value="hidden">* Unsichtbar</option>');
  wl('<option value="html">* HTML</option>');
  wl('<option value="-">Bausteine</option>');
  wl('<option value="keywords">* Keywords</option>');
  wl('<option value="include">* Include</option>');
  wl('<option value="style">* StyleSheet</option>');
  wl('<option value="macrodef">* MacroDef</option>');
  wl('<option value="script">* JavaScript</option>');
  wl('<option value="wscript">* WikiScript</option>');
  wl('</select>');
  wl('</td></tr></table>');
}


More Page Infos / Sitemap
Created Dienstag, 17. Juni 2014
Scroll to Top of Page
Changed Sonntag, 28. Februar 2016