#pragma TextEncoding="UTF-8" #pragma rtGlobals=3 #pragma version=1.07 #pragma IgorVersion=6.30 #pragma moduleName=CalcPad // If you're using Igor Pro 7 or later, this package can check // periodically for new releases if you've installed Project Updater. // http: www.igorexchange.com/project/Updater static constant kCHECK_FOR_UPDATES=1 // set to 1 to check for updates on init // by tony.withers@uwo.ca // Use the shortcut "cmd + 9" to start CalcPad. CalcPad turns a notebook // into a command-line type interface. Use up and down arrows to insert // previously executed lines. Use shift-up/down to replace selection with // previous answers. Execution environment is current data folder. Global // variables v_CalcPad and s_CalcPad are created temporarily in the // current data folder. Type ? and hit enter to change package // preferences. // If you find this package to be useful, I recommend editing the next // line of code to convert this procedure to an independent module. // Simply change the 0 to 1. If you put this file in the Igor Procedures // folder CalcPad will then be always available using the cmd + 9 // shortcut or through the Analysis > Packages menu. The default setting // of 0 allows you to read this file and test the package. #if 0 #pragma IndependentModule = CalcPad menu "Analysis" submenu "Packages" "CalcPad/9", /Q, CalcPad#CalcPad#CalcPad() end end #else menu "Macros" "CalcPad/9", /Q, CalcPad#CalcPad() end #endif static function CalcPad() if (CheckForUpdates()) return 0 // this file has been updated; quit to allow user to reload endif DFREF dfr = getDFR() // create package folder and populate s_prefs SVAR s_prefs=dfr:s_prefs STRUCT PackagePrefs prefs structGet /S prefs, s_prefs if(waveexists(dfr:w_history)==0) make /o/T/N=0 dfr:w_history, dfr:w_answers variable /G dfr:v_ans=0, dfr:v_hist=0 endif if (strlen(WinList("CalcPadNB", ";", "WIN:16"))) dowindow /F CalcPadNB else NewNotebook /K=1 /F=1 /W=(prefs.win.left, prefs.win.top, prefs.win.right, prefs.win.bottom) /N=CalcPadNB as "CalcPad" notebook CalcPadNB showRuler=0, fSize=prefs.font_size, magnification=prefs.magnification notebook CalcPadNB backRGB=(prefs.RGB_bg.red, prefs.RGB_bg.green, prefs.RGB_bg.blue) notebook CalcPadNB textRGB=(prefs.RGB_txt.red, prefs.RGB_txt.green, prefs.RGB_txt.blue) endif string funcStr=GetIndependentModuleName()+"#CalcPad#CalcPadHook" SetWindow CalcPadNB, hook(hCalcPad)=$(funcStr) return 1 end // creates package folder, loads preferences into a structure and 'puts' // structure into a string static function /DF getDFR() NewDataFolder /O root:Packages NewDataFolder /O root:Packages:CalcPad DFREF dfr = root:Packages:CalcPad string /G dfr:S_prefs SVAR s_prefs=dfr:S_prefs STRUCT PackagePrefs prefs LoadPackagePreferences "CalcPad", "CalcPadPrefs.bin", 0, prefs if (V_flag!=0 || V_bytesRead==0) CalPadSetDefaults(prefs) endif structPut /S prefs, s_prefs return dfr end static function CalPadSetDefaults(prefs) STRUCT PackagePrefs &prefs prefs.version=101 prefs.font_size=14 prefs.magnification=100 prefs.win.left=0 prefs.win.top=0 prefs.win.right=350 prefs.win.bottom=300 prefs.RGB_bg.red=65535 prefs.RGB_bg.green=65535 prefs.RGB_bg.blue=65535 prefs.RGB_txt.red=0 prefs.RGB_txt.green=0 prefs.RGB_txt.blue=0 prefs.RGB_ans.red=0 prefs.RGB_ans.green=0 prefs.RGB_ans.blue=65280 prefs.options.EnterCopy=1 prefs.options.InLine=1 prefs.options.StringEval=1 prefs.options.SigFigs=12 SavePackagePreferences "CalcPad", "CalcPadPrefs.bin", 0, prefs SVAR s_prefs=root:Packages:CalcPad:S_prefs if (svaR_Exists(s_prefs)) structPut /S prefs, s_prefs endif // if prefs panel is open, reset controls PopupMenu /Z popupBG,win=CalcPadPrefsPanel,popColor= (prefs.RGB_bg.red,prefs.RGB_bg.green,prefs.RGB_bg.blue),value= #"\"*COLORPOP*\"" PopupMenu /Z popupTXT,win=CalcPadPrefsPanel,popColor= (prefs.RGB_txt.red,prefs.RGB_txt.green,prefs.RGB_txt.blue),value= #"\"*COLORPOP*\"" PopupMenu /Z popupANS,win=CalcPadPrefsPanel,popColor= (prefs.RGB_ans.red,prefs.RGB_ans.green,prefs.RGB_ans.blue),value= #"\"*COLORPOP*\"" CheckBox /Z checkEnter,win=CalcPadPrefsPanel,value= prefs.options.EnterCopy CheckBox /Z checkString,win=CalcPadPrefsPanel,value= prefs.options.InLine CheckBox /Z checkInline,win=CalcPadPrefsPanel,value= prefs.options.StringEval doWindow CalcPadNB if(V_flag) notebook CalcPadNB backRGB=(prefs.RGB_bg.red,prefs.RGB_bg.green,prefs.RGB_bg.blue) endif end static function CalcPadHook(H_Struct) STRUCT WMWinHookStruct &H_Struct DFREF dfr = root:Packages:CalcPad wave /T w_hist=dfr:w_history, w_ans=dfr:w_answers NVAR v_ans=dfr:v_ans, v_hist=dfr:v_hist SVAR s_prefs=dfr:s_prefs STRUCT PackagePrefs prefs structGet /S prefs, s_prefs if(H_Struct.eventcode==11) // keyboard event if(H_Struct.keycode==28 || H_Struct.keycode==29) // left or right arrow return 0 // allow these for selecting text endif // make sure that we're typing on the last line GetSelection notebook, CalcPadNB, 1 // get current position in notebook // store position make /free w={V_startParagraph, V_startPos, V_endParagraph, V_endPos} // find last paragraph notebook CalcPadNB selection={endOfFile,endofFile} GetSelection notebook, CalcPadNB, 1 if (V_startParagraph==w[0]) // we're writing on the last line // restore current position notebook CalcPadNB selection={(w[0],w[1]), (w[2],w[3])} else if(prefs.options.EnterCopy && (H_Struct.keycode==13 || H_Struct.keycode==3)) // return or enter notebook CalcPadNB selection={(w[0],w[1]), (w[2],w[3])} GetSelection notebook, CalcPadNB, 2 // sets S_selection notebook CalcPadNB selection={endOfFile,endofFile} if (strlen(s_selection)) Notebook CalcPadNB text=s_selection endif endif notebook CalcPadNB findText={"",1} // jump to end of last line return 1 endif // this allows select, copy within notebook // typing allowed on the last line only // trying to type elsewhere sends cursor to end of file if (H_Struct.keycode==30 || H_Struct.keycode==31) // up or down arrow string insertStr if (H_Struct.eventMod & 2) // shift key // replace currently highlighted text with a previous answer GetSelection notebook, CalcPadNB, 1 w={V_startParagraph, V_startPos, V_endParagraph, V_endPos} v_ans+=1-2*(H_Struct.keycode==30) v_ans=max(0, v_ans) if (v_ansnumpnts(w_hist)-1) insertStr="" else insertStr=w_hist(v_hist) endif v_hist=min(v_hist, numpnts(w_hist)) notebook CalcPadNB text=insertStr notebook CalcPadNB selection={endOfFile,endofFile} endif return 1 endif if (H_Struct.keycode==8) // delete GetSelection notebook, CalcPadNB, 1 // get current position in notebook if(V_startPos==0 && V_endPos==0) // Don't delete the start of the last line return 1 endif endif if (H_Struct.keycode==13 || H_Struct.keycode==3) // return or enter // select the last paragraph notebook CalcPadNB selection={startOfParagraph, endOfChars} GetSelection notebook, CalcPadNB, 2 // sets S_selection if (strlen(s_selection)==0) return 1 endif if(stringmatch(S_selection, "?")) notebook CalcPadNB text="" makePrefsPanel() return 1 endif notebook CalcPadNB selection={endOfParagraph, endOfParagraph} w_hist[numpnts(w_hist)]={s_selection} v_hist=numpnts(w_hist) variable /G V_CalcPad=nan // work with a global variable in the current data folder so that // we can be folder aware execute /z/q "v_CalcPad = "+S_selection NVAR v_result=v_CalcPad string resultStr="", formatStr="%."+num2str(prefs.options.sigFigs)+"g" if(prefs.options.StringEval && numtype(v_result)!=0) // not a normal number, so try to evaluate as text string /G s_CalcPad="" execute /Z/Q "s_CalcPad = "+S_selection if (strlen(s_CalcPad)) sprintf resultStr, "\"%s\"", s_CalcPad else sprintf resultStr, formatStr, v_result endif else sprintf resultStr, formatStr, v_result endif w_ans[numpnts(w_ans)]={resultStr} v_ans=numpnts(w_ans) notebook CalcPadNB textRGB=(prefs.RGB_ans.red,prefs.RGB_ans.green,prefs.RGB_ans.blue) if(prefs.options.InLine) Notebook CalcPadNB text=" = " else Notebook CalcPadNB text="\r\t" endif Notebook CalcPadNB text=resultStr +"\r" notebook CalcPadNB textRGB=(prefs.RGB_txt.red,prefs.RGB_txt.green,prefs.RGB_txt.blue) KillVariables /Z v_result KillStrings /Z s_CalcPad return 1 endif endif if(H_Struct.eventcode==10) // menu if (stringmatch(H_Struct.menuItem, "Paste")) GetSelection notebook, CalcPadNB, 1 // get current position in notebook // store position make /free w={V_startParagraph, V_startPos, V_endParagraph, V_endPos} // find last paragraph notebook CalcPadNB selection={endOfFile,endofFile} GetSelection notebook, CalcPadNB, 1 if (V_startParagraph==w[0]) // we're writing on the last line // restore current position notebook CalcPadNB selection={(w[0],w[1]), (w[2],w[3])} else // trying to paste somewhere else return 1 endif endif endif if(H_Struct.eventcode==2) // kill window string recreation=winRecreation(H_Struct.winName, 0) variable index, top, left, bottom, right, mag // save window position index=strsearch(recreation, "/W=(", 0) if (index>0) sscanf recreation[index,strlen(recreation)-1], "/W=(%g,%g,%g,%g)", left, top, right, bottom prefs.win.top=top prefs.win.left=left prefs.win.bottom=bottom prefs.win.right=right endif // save window magnification index=strsearch(recreation, "magnification=", 0) if (index>0) sscanf recreation[index,inf], "magnification=%g", mag prefs.magnification=mag endif SavePackagePreferences "CalcPad", "CalcPadPrefs.bin", 0, prefs killdatafolder /Z dfr endif return 0 end // 200 byte structure static structure PackagePrefs uint32 version // Preferences structure version number. 100 means 1.00. uint32 font_size uint32 magnification STRUCT Rect win // window position and size, 8 bytes STRUCT RGBColor RGB_bg // 6 bytes STRUCT RGBColor RGB_txt STRUCT RGBColor RGB_ans STRUCT PackageOptions options // 40 bytes char reserved[200 - 3*4 - 8 - 3*6 - 40] // Reserved for future use endStructure // substructure, total size 40 bytes static structure PackageOptions uint16 EnterCopy // allow enter key to copy selected history text to end of last line uint16 InLine // answers on same line as input uint16 StringEval // allow fallback to string evaluation uint16 SigFigs // number of significant figures to display char reserved[40-4*2] // Reserved for future use endStructure static function makePrefsPanel() DFREF dfr = getDFR() // create dfr and populate s_prefs SVAR s_prefs=dfr:s_prefs STRUCT PackagePrefs prefs structGet /S prefs, s_prefs doWindow /K CalcPadPrefsPanel variable WL=150, WT=100, WR=WL+247, WB=WT+350 NewPanel /K=1/N=CalcPadPrefsPanel/W=(WL,WT,WR,WB) ModifyPanel /W=CalcPadPrefsPanel , fixedSize=1 variable vLeft=30, vTop=20, i=0 i+=0.5 GroupBox group0,pos={vLeft-10,i*30},size={210.00,120.00},title="Colours",fSize=12 i+=1 PopupMenu popupBG,win=CalcPadPrefsPanel,pos={vLeft,i*30},size={169.00,23.00},title="Window background", proc=$(getIndependentModuleName()+"#CalcPad#PopMenuProc") PopupMenu popupBG,win=CalcPadPrefsPanel,fSize=12,mode=1,popColor= (prefs.RGB_bg.red,prefs.RGB_bg.green,prefs.RGB_bg.blue),value= #"\"*COLORPOP*\"" i+=1 PopupMenu popupTXT,win=CalcPadPrefsPanel,pos={vLeft,i*30},size={78.00,23.00},title="Text",fSize=12, proc=$(getIndependentModuleName()+"#CalcPad#PopMenuProc") PopupMenu popupTXT,win=CalcPadPrefsPanel,mode=1,popColor= (prefs.RGB_txt.red,prefs.RGB_txt.green,prefs.RGB_txt.blue),value= #"\"*COLORPOP*\"" i+=1 PopupMenu popupANS,win=CalcPadPrefsPanel,pos={vLeft,i*30},size={101.00,23.00},title="Answers", proc=$(getIndependentModuleName()+"#CalcPad#PopMenuProc") PopupMenu popupANS,win=CalcPadPrefsPanel,fSize=12,mode=1,popColor= (prefs.RGB_ans.red,prefs.RGB_ans.green,prefs.RGB_ans.blue),value= #"\"*COLORPOP*\"" i+=1.5 GroupBox group1,win=CalcPadPrefsPanel,pos={vLeft-10,i*30},size={210.00,150.00},title="Options",fSize=12 i+=1 CheckBox checkEnter,win=CalcPadPrefsPanel,pos={vLeft,i*30},size={141.00,16.00},title="Use enter key to copy" CheckBox checkEnter,win=CalcPadPrefsPanel,fSize=12,value= prefs.options.EnterCopy, proc=$(getIndependentModuleName()+"#CalcPad#CheckProc") i+=1 CheckBox checkString,win=CalcPadPrefsPanel,pos={vLeft,i*30},size={179.00,16.00},title="Fall back to string evaluation" CheckBox checkString,win=CalcPadPrefsPanel,fSize=12,value= prefs.options.InLine, proc=$(getIndependentModuleName()+"#CalcPad#CheckProc") i+=1 CheckBox checkInline,win=CalcPadPrefsPanel,pos={vLeft,i*30},size={168.00,16.00},title="Print answers on same line" CheckBox checkInline,win=CalcPadPrefsPanel,fSize=12,value= prefs.options.StringEval, proc=$(getIndependentModuleName()+"#CalcPad#CheckProc") i+=1 SetVariable setSigFigs, win=CalcPadPrefsPanel,pos={vLeft,i*30},size={168.00,16.00},title="Significant Figures" SetVariable setSigFigs, win=CalcPadPrefsPanel, fSize=12,value=_NUM:prefs.options.SigFigs, proc=$(getIndependentModuleName()+"#CalcPad#SetvarProc") i+=1.5 Button buttonReset,win=CalcPadPrefsPanel,pos={vLeft,i*30},size={100.00,20.00},title="Set to defaults", proc=$(getIndependentModuleName()+"#CalcPad#ButtonProc") end static function ButtonProc(ba) STRUCT WMButtonAction &ba if(ba.eventCode==2) STRUCT PackagePrefs prefs CalPadSetDefaults(prefs) DFREF dfr = getDFR() // create dfr and populate s_prefs SVAR s_prefs=dfr:s_prefs structGet /S prefs, s_prefs SetVariable /Z setSigFigs, win=CalcPadPrefsPanel, value=_NUM:prefs.options.SigFigs endif return 0 End static function CheckProc(cba) STRUCT WMCheckboxAction &cba if(cba.eventCode==2) DFREF dfr = getDFR() // create dfr and populate s_prefs SVAR s_prefs=dfr:s_prefs STRUCT PackagePrefs prefs structGet /S prefs, s_prefs strswitch(cba.ctrlName) case "checkEnter": prefs.options.EnterCopy= cba.checked break case "checkInline": prefs.options.InLine=cba.checked break case "checkString": prefs.options.StringEval=cba.checked break endswitch SavePackagePreferences "CalcPad", "CalcPadPrefs.bin", 0, prefs structPut /S prefs, s_prefs endif return 0 End static function SetVarProc(sva) STRUCT WMSetVariableAction &sva switch( sva.eventCode ) case 1: // mouse up case 2: // enter key case 3: // Live update DFREF dfr = getDFR() // create dfr and populate s_prefs SVAR s_prefs=dfr:s_prefs STRUCT PackagePrefs prefs structGet /S prefs, s_prefs prefs.options.sigFigs=sva.dval SavePackagePreferences "CalcPad", "CalcPadPrefs.bin", 0, prefs structPut /S prefs, s_prefs break case -1: // control being killed break endswitch return 0 End static function PopMenuProc(pa) STRUCT WMPopupAction &pa if(pa.eventCode ==2) DFREF dfr = getDFR() // create dfr and populate s_prefs SVAR s_prefs=dfr:s_prefs STRUCT PackagePrefs prefs structGet /S prefs, s_prefs ControlInfo $pa.ctrlName strswitch(pa.ctrlName) case "popupBG": prefs.RGB_bg.red=V_red prefs.RGB_bg.green=V_green prefs.RGB_bg.blue=V_blue doWindow CalcPadNB if(V_flag) notebook CalcPadNB backRGB=(V_red, V_green, V_blue) endif break case "popupTXT": prefs.RGB_txt.red=V_red prefs.RGB_txt.green=V_green prefs.RGB_txt.blue=V_blue break case "popupANS": prefs.RGB_ans.red=V_red prefs.RGB_ans.green=V_green prefs.RGB_ans.blue=V_blue break endswitch SavePackagePreferences "CalcPad", "CalcPadPrefs.bin", 0, prefs structPut /S prefs, s_prefs endif return 0 End // ---------------- code used to check for updates --------------------- static function CheckForUpdates() if (kCHECK_FOR_UPDATES==0) return 0 endif string keyStr="" keyStr=ReplaceStringByKey("fileloc", keyStr, FunctionPath("")) // find out whether Updater is installed #if (exists("Updater#UpdateCheck")==6) // this will be 0 if running as an independent module return Updater#UpdateCheck(keyStr) #endif if(stringmatch(GetIndependentModuleName(), "ProcGlobal")) return 0 endif // Running as independent module, so will have to use execute. // Find out whether procedures are compiled: variable /G V_updated=0 variable isUpdated=0 string cmd, infoStr=FunctionInfo("ProcGlobal#updater#UpdateCheck", "Updater.ipf") if (stringmatch(StringByKey("MODULE", infoStr), "updater")) // updater is available AND compiled sprintf cmd, "V_updated=ProcGlobal#Updater#UpdateCheck(\"%s\")", keyStr execute cmd isUpdated=V_updated endif killvariables /Z V_updated return isUpdated end