// // LineNumbers.vdm Christian Ziemski 15.02.2006 only the GUI // 19.02.2006 // 22.02.2006 now with functionality // 23.02.2006 changed the size of dialog // some fixes and enhancements // 02.03.2006 new default option handling // // Please note: // // - Don't retab this macro! That would destroy the dialog construction! // // - The divider has a default of " " (one space). // Due to it's nature this space isn't easily visible in the dialog. // //====================================================================== // // Questions: // // Perhaps it's a good idea to check whether the current buffer has // an assigned filename. Since the file may grow significantly due // to the inserted numbers the buffer may overflow otherwise. // //====================================================================== // // Register usage: // // #80 line number of block begin // #81 line number of block end (or MAXNUM for all lines) // #82 OPTION(s) for Num_Ins() // #83 max number to be inserted // #84 width of #83 // #89 button# from dialog // // #90-#99 see below // // #103 misc usage // #104 misc usage // #105 misc usage // // $92 divider string, see below // $95 Title string // $96 error msg for title string // // $103 misc usage // $104 misc usage // // Marker(9) // //====================================================================== Reg_Push(90,99) // save the used registers Num_Push(80,99) //====================================================================== // The defaults for the dialog options // (the ones regarding a highlighted block are changed automatically later) // // If there is a file "linenumbers.opt" in VEDIT's home directory, the // there included options are used instead of the hardcoded ones below. // Within the dialog you can set new default values. //---------------------------------------------------------------------- Reg_Set(95, "Line Numbering") // title string if (File_Exist("|(HOME)\linenumbers.opt")) { Call_File(103, "|(HOME)\linenumbers.opt") goto DIALOG } #90=2 // 1 = Block, 2 = whole file #91=1 // 1 = Begin of File/Block, 2 = cursor pos #92=1 // 1 = real line numbers, 2 = counter #93=1 // 0 = no padding 1 = padded // only of interest with padding enabled (#93=1) #94=2 // 1 = with leading spaces 2 = with leading 0's #95=1 // 0 = fixed width dependant on max number (5,10/19 digits) // 1 = minimized fixed width // only of interest with #92=2 (counter enabled) #98=10 // first number (default) #99=10 // increment (default) //---------------------------------------------------------------------- // the divider between number and text line #96=0 // 0 = divider literally // 1 = divider interpreted as hex/dec values #97=0 // no auto execute option (not yet implemented) Reg_Set(92, " ") // Examples for the usage of hex/dec values: // // Reg_Set(92, "9") // a TAB (if #96=1) (decimal) // Reg_Set(92, "0x20") // a space (if #96=1) (hex) // Reg_Set(92, "9 0x20") // a TAB and a space (if #96=1) // //====================================================================== :DIALOG: if (Block_Begin == -1) { // no block highlighted #90=2 } else { #90=1 // else set dialog option to "block" } // if (#97) { // auto execution (no dialog) # not yet implemented // Goto MAIN // } Num_Str(#98,90, LEFT) // convert numbers to strings for display Num_Str(#99,91, LEFT) #89=Dialog_Input_1(90,"`|@(95) |@(96)`, `This macro inserts line numbers in front of lines of text.`, `It does it's work within the`, `.h.g.r.s() &highlighted block or `, `() the &whole file`, `beginning at the`, `.h.g.r() &Begin_of_File/Block or `, `() current &cursor position`, `The inserted numbers are`, `.h.g.r() the real &line numbers or `, `() a cou&nter with`, `.g.r?? &first value `, `?? and &increment`, `.t[] &padded with`, `.h.g.r() leading &spaces or `, `() &0's`, `.t.s.s.s.s.s.s.qto a fixed `,`.h.l[] &minimized`, `.h.lwidth,`, `?? using as ÷r:`, `.t[] interpreted as space-sep. he&x/dec values`, `.i.b[&Ok]`,`[Canc&el]`, `[Save as default]`", SET+APP+CENTER,0,0) if ((#89 != 1) && (#89 != 3)) { // if [cancel] or ESC Num_Pop(80,99) // restore the used registers Reg_Pop(90,99) return // and leave } // Check the input and repeat the dialog if needed Reg_Empty(96) // the error register if (#92==1) { // if counter not checked if ((Num_Eval_Reg(90) != #98) || (Num_Eval_Reg(91) != #99)) { // but values are changed #92=2 // set to "counter" Reg_Set(96, " >>> Counter is now enabled. O.k.?") // and give it to dialog again #98=Num_Eval_Reg(90) // convert strings back to numbers #99=Num_Eval_Reg(91) Goto DIALOG } } #98=Num_Eval_Reg(90) // convert strings back to numbers #99=Num_Eval_Reg(91) if (#89 == 3) { // if "Save as default options" #103=Buf_Num Buf_Switch(Buf_Free) Ins_Text(" #90=") Num_Ins(#90, LEFT+NOCR) Ins_Text(" #91=") Num_Ins(#91, LEFT+NOCR) Ins_Text(" #92=") Num_Ins(#92, LEFT+NOCR) Ins_Text(" #93=") Num_Ins(#93, LEFT+NOCR) Ins_Text(" #94=") Num_Ins(#94, LEFT+NOCR) Ins_Text(" #95=") Num_Ins(#95, LEFT+NOCR) Ins_Text(" #96=") Num_Ins(#96, LEFT+NOCR) Ins_Text(" #97=") Num_Ins(#97, LEFT+NOCR) Ins_Text(" #98=") Num_Ins(#98, LEFT+NOCR) Ins_Text(" #99=") Num_Ins(#99, LEFT+NOCR) Ins_Text(' Reg_Set(92,"') Reg_Ins(92) Ins_Text('")') File_Save_As("|(HOME)\linenumbers.opt", OK+NOMSG) Buf_Quit(OK) Buf_Switch(#103) Goto DIALOG // back to the dialog } :MAIN: // Determine the characters of the divider string // // If a value can't be evaluated (and so is zero) an error is // shown and the dialog is repeated. // (That means that no ASCII value of 0x00 is possible within the divider.) if (#96==1) { // divider should be interpreted as hex/dec #103=Buf_Num Buf_Switch(Buf_Free) Reg_Ins(92) BoF Reg_Empty(104) Out_Reg(104, APPEND) while (! At_EOF) { #104=Num_Eval(SUPPRESS+ADVANCE) if (#104==0) { Reg_Set(96, " >>> Error in divider string") Search("|{|W,|<}", REVERSE+NOERR+ADVANCE) Ins_Text(">>>") // mark error with ">>>" Reg_Copy_Block(92, 0, EoL_Pos) break } Char_Dump(#104, NOCR) } Out_Reg(CLEAR) Buf_Quit(OK) Buf_Switch(#103) if (#104==0) { Goto DIALOG } Reg_Set(92, @104) // copy the calculated divider back to T-Reg 92 } // Start the real work: // Preparations regarding blocks // Evaluate and fix the first and last line to be numbered // Goto start line #98=Num_Eval_Reg(90) // convert strings back to numbers #99=Num_Eval_Reg(91) Set_Marker(9, Cur_Pos) if (#90==1) { // work within highlighted block if (Block_End==-1) { // if no block_end set Block_End(Cur_Pos) // set it to current cursor position } if (Block_Begin > Block_End) { // if block was highlighted bottom up Goto_Pos(Block_End) #80=Cur_Line BoL if (At_EoL) { #80++ } Goto_Pos(Block_Begin) } else { // else it was highlighted top down Goto_Pos(Block_Begin) #80=Cur_Line Goto_Pos(Block_End) } #81=Cur_Line if (At_BoL) { #81-- } if (#91==1) { // from BoB Goto_Line(#80) } else { // from Cur_Pos Goto_Pos(Marker(9)) Begin_Of_Line } } else { // use no highlighted block #80=1 End_Of_File #81=Cur_Line if (#91==1) { // from BoF Begin_Of_File } else { // from Cur_Pos Goto_Pos(Marker(9)) Begin_Of_Line } } // Determine the maximum number if (#92==1) { // real line number #83=#81 } else { // counter #83 = #98 + (#81-#80)*#99 } // and the width of this number (for display purpose) Num_Str(#83, 103, LEFT+NOCR) #84=Reg_Size(103) // Preparations for Num_Ins() #82 = NOCR + FILL*(#94-1) + LEFT*(#93==0) if (#95==0) { // if not minimized width #82 = #82 + FORCE*(#83>99999) } // Main loop to insert the numbers while (! At_EoF) { if (#92==1) { // real line number #103=Cur_Line } else { // counter #103=#98 #98 = #98 + #99 } if ((#95==0) || (#93==0)) { // (not minimized width) or (not padded) Num_Ins(#103, #82) } else { // minimized width Num_Str(#103, 103, LEFT+NOCR+FILL*(#94-1)) #104=Reg_Size(103) Ins_Char(32+16*(#94-1), COUNT, #84-#104) Reg_Ins(103) } Reg_Ins(92) // divider between number and text Line(1, ERRBREAK) if (Cur_Line > #81) { break } } // Fix Block_Begin and Block_End optically if (#90==1) { // work within highlighted block Goto_Line(#80) BoL Block_Begin(Cur_Pos) Goto_Line(#81) EoL Line(1,NOERR) Block_End(Cur_Pos) } // Clean up Goto_Pos(Marker(9)) // restore cursor position Set_Marker(9, CLEAR) Num_Pop(80,99) // restore the used registers Reg_Pop(90,99) Reg_Empty(103) Reg_Empty(104) Key_Purge() // to be sure to have kept all keystrokes