Newsgroups: comp.sources.unix From: mik@cs.su.oz.au (Michael Koelling) Subject: v29i101: red-96 - a GUI text editor for UNIX/X/Motif, Part06/09 References: <1.831971879.6147@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: mik@cs.su.oz.au (Michael Koelling) Posting-Number: Volume 29, Issue 101 Archive-Name: red-96/part06 #!/bin/sh # This is `part06' (part 6 of a multipart archive). # Do not concatenate these parts, unpack them in order with `/bin/sh'. # File `Red/Red/finder.cc' is being continued... # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # if test ! -r _sharseq.tmp; then echo 'Please unpack part 1 first!' exit 1 fi shar_sequence=`cat _sharseq.tmp` if test "$shar_sequence" != 6; then echo "Please unpack part $shar_sequence next!" exit 1 fi if test ! -f _sharnew.tmp; then echo 'x - still skipping Red/Red/finder.cc' else echo 'x - continuing file Red/Red/finder.cc' sed 's/^X//' << 'SHAR_EOF' >> 'Red/Red/finder.cc' && X// File: finder.cc -mik- 1995 X// X// Implementation of class FINDER. See finder.h for description. X// Finder is part of the Blue programming environment. X// ============================================================================ X X#include X#include X#include X X#include "finder.h" X#include "../Utility/utility.h" X#include "../Utility/messages.h" X#include "../Utility/debug.h" X X// ============================= CALLBACKS ================================= X X// any button in the find dialog: X Xvoid find_dlg_cb (Widget w, XtPointer button, XtPointer call_data) X{ X int ac; X Arg al[10]; X FINDER* finder; X X // extract object pointer from widget user data X X ac=0; X XtSetArg (al[ac], XmNuserData, &finder); ac++; X XtGetValues (w, al, ac); X X switch ((int)button) { X case 0: finder->button1 (); X break; X case 1: finder->button2 (); X break; X case 2: finder->replace_all (); X break; X case 3: finder->close_dlg (); X break; X case 4: finder->insert_special ('\n'); X break; X case 5: finder->insert_special ('\t'); X break; X } X} X X// ========================== END OF CALLBACKS ============================== X X// ------------------------------------------------------------------------- X// FINDER: Constructor. X// ------------------------------------------------------------------------- X XFINDER::FINDER (Widget prnt) X : NLChar(0xb6), TABChar(0xbb) X{ X parent = prnt; X editor = NULL; X X find_dlg = NULL; X pattern = NULL; X replace_pattern = NULL; X case_sens = False; X word = False; X dir = forwd; X X find_title = XmStringCreateSimple ("Red: Find"); X replace_title = XmStringCreateSimple ("Red: Replace"); X} X X// ------------------------------------------------------------------------- X// ~FINDER: Destructor. Destroy the dialog widget. X// ------------------------------------------------------------------------- X XFINDER::~FINDER () X{ X if (find_dlg != NULL) X XtDestroyWidget (find_dlg); X} X X// ------------------------------------------------------------------------- X// show_find_dlg: Display the find dialog. X// ------------------------------------------------------------------------- X Xvoid FINDER::show_dialog (Boolean show_replace, EDITOR* ed, Boolean backw) X{ X assert (editor == NULL); // check that we have only one dialog open X X editor = ed; X if (find_dlg == NULL) // create it if it doesn't exists already X create_dialog (); X X if (show_replace) { // show replace dialog X make_replace_dialog (); // make sure it is the replace version X } X else { // show find dialog X make_find_dialog (backw); // make sure it is the find version X XmTextSetString (find_text, ""); X } X XtManageChild (find_dlg); // show it X} X X// ------------------------------------------------------------------------- X// get_find_info: Return all the information available about the last X// find operation (for "find_next"). X// ------------------------------------------------------------------------- X Xvoid FINDER::get_find_info (char*& search_pattern, SearchDir& direction, X Boolean& case_matters, Boolean& whole_word) X{ X search_pattern = pattern; X direction = dir; X case_matters = case_sens; X whole_word = word; X} X X// ------------------------------------------------------------------------- X// set_find_string: Define the string used for next find operation. X// ------------------------------------------------------------------------- X Xvoid FINDER::set_find_string (char* str) X{ X XtFree (pattern); X pattern = str; X} X X // ========================================================================= X// private functions X// ========================================================================= X X// ------------------------------------------------------------------------- X// button1: Button number 1 has been pressed. Check which dialog we have X// and call the appropriate routine (which is "find_forward" if we have X// a find dialog, or "find_next" if it is a replace dialog). X// ------------------------------------------------------------------------- X Xvoid FINDER::button1 () X{ X if (which_dlg == FindDialog) X find (forwd); X else X find_next (); X} X X// ------------------------------------------------------------------------- X// button2: Button number 2 has been pressed. Check which dialog we have X// and call the appropriate routine (which is "find_backward" if we X// have a find dialog, or "replace" if it is a replace dialog). X// ------------------------------------------------------------------------- X Xvoid FINDER::button2 () X{ X if (which_dlg == FindDialog) X find (backwd); X else X replace (); X} X X// ------------------------------------------------------------------------- X// replace_all: Replace all instances of a pattern with another one up to X// the end of the file (in the specified direction). X// ------------------------------------------------------------------------- X Xvoid FINDER::replace_all () X{ X assert (editor != NULL); X get_search_values (); X get_replace_pattern (); X X editor->do_replace_all (pattern, dir, case_sens, word, replace_pattern); X utility->set_sensitive (but_button2, False); X} X X// ------------------------------------------------------------------------- X// close_dlg: Close the find or replace dialog. X// ------------------------------------------------------------------------- X Xvoid FINDER::close_dlg () X{ X assert (editor != NULL); // check that we have only one dialog open X X XtUnmanageChild (find_dlg); X editor = NULL; X} X X// ------------------------------------------------------------------------- X// insert_special: Insert a special character (LF, TAB) into the search X// pattern. X// ------------------------------------------------------------------------- X Xvoid FINDER::insert_special (char ch) X{ X char s[2]; X int pos; X Widget focus_widget; X X s[1] = '\0'; X if (ch == '\n') X s[0] = NLChar; X else X s[0] = ch; X focus_widget = XmGetFocusWidget (find_dlg); X if ((focus_widget == find_text) || (focus_widget == replace_text)) { X pos = XmTextGetInsertionPosition (focus_widget); X XmTextInsert (focus_widget, pos, s); X XmTextSetInsertionPosition (focus_widget, pos+1); X } X} X X// ------------------------------------------------------------------------- X// find: The "find forward" or "find backward" button in the dialog was X// clicked. Call the editor to perform the find and close the dialog X// window. X// ------------------------------------------------------------------------- X Xvoid FINDER::find (SearchDir direction) X{ X get_search_values (); X dir = direction; X X assert (editor != NULL); X editor->do_find (pattern, dir, case_sens, word); // discard result X close_dlg (); X} X X// ------------------------------------------------------------------------- X// find_next: Used in the replace dialog. Find the next occurrence of X// the pattern with the options specified in the current replace X// dialog. X// ------------------------------------------------------------------------- X Xvoid FINDER::find_next () X{ X get_search_values (); X X assert (editor != NULL); X if (editor->do_find (pattern, dir, case_sens, word)) X utility->set_sensitive (but_button2, True); X else X utility->set_sensitive (but_button2, False); X} X X X// ------------------------------------------------------------------------- X// replace: The replace button in the dialog has been pressed. Get the X// replace text and perform the replace. This should only be possible X// if a find was successful, meaning that a current selection must X// exist. If not, the editor function do_replace will return False. X// This should not happen. We have to ensure that replace can only be X// called with a selection on. X// After a successful replace, we try to find the next occurrence of X// pattern. X// ------------------------------------------------------------------------- X Xvoid FINDER::replace () X{ X get_replace_pattern (); X assert (editor->do_replace (replace_pattern)); X find_next (); X} X X// ------------------------------------------------------------------------- X// get_search_values: Read the values out of the dialog widgets into the X// global variables holding the find parameters. X// ------------------------------------------------------------------------- X Xvoid FINDER::get_search_values () X{ X unsigned char* p; X X XtFree (pattern); X pattern = XmTextGetString (find_text); X for (p=(unsigned char*)pattern; *p; p++) // replace newline display X if (*p == NLChar) *p = '\n'; // character with newline X case_sens = utility->read_toggle (but_case); X word = utility->read_toggle (but_word); X if (utility->read_toggle (but_direction)) X dir = backwd; X else X dir = forwd; X} X X// ------------------------------------------------------------------------- X// get_replace_pattern: Read the value out of the replace text widget into X// the global variable holding the replace text. X// ------------------------------------------------------------------------- X Xvoid FINDER::get_replace_pattern () X{ X unsigned char* p; X X XtFree (replace_pattern); X replace_pattern = XmTextGetString (replace_text); X for (p=(unsigned char*)replace_pattern; *p; p++) // replace newline display X if (*p == NLChar) *p = '\n'; // character with newline X} X X// ------------------------------------------------------------------------- X// create_dialog: Create the dialog that is used for both, find and X// replace. It is created as the replace dialog and can be changed X// later to be used for find. The dialog is not yet managed. X// ------------------------------------------------------------------------- X Xvoid FINDER::create_dialog () X{ X int ac; X Arg al[10]; X X Widget button_area, input_area, insert_area, toggle_area; X Widget ins_label, but_ins_lf, but_ins_tab; X X /* create a window for the dialog */ X X ac=0; X XtSetArg (al[ac], XmNnoResize, True); ac++; X XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); ac++; X XtSetArg (al[ac], XmNautoUnmanage, False); ac++; X XtSetArg (al[ac], XmNhorizontalSpacing, 20); ac++; X XtSetArg (al[ac], XmNverticalSpacing,20); ac++; X XtSetArg (al[ac], XmNmwmDecorations, 2 | 8); ac++; // border and title X XtSetArg (al[ac], XmNdialogTitle, replace_title); ac++; X find_dlg = XmCreateFormDialog (parent, "DialogFind", al, ac); X X X /* create a button area with the buttons */ X X button_area = utility->create_rc_area (find_dlg, "buttonArea", XmVERTICAL, X XmALIGNMENT_CENTER); X utility->attach (button_area, NULL, AtForm, AtForm, AtForm); X X but_button1 = utility->create_button (button_area, "Find Next", X find_dlg_cb, 0, this); X but_button2 = utility->create_button (button_area, "Replace", X find_dlg_cb, 1, this); X but_repl_all = utility->create_button (button_area, "Replace All", X find_dlg_cb, 2, this); X but_help = utility->create_button (button_area, "Help", X show_help, HlpFind, this); X but_close = utility->create_button (button_area, "Close", X find_dlg_cb, 3, this); X ac=0; X XtSetArg (al[ac], XmNdefaultButton,but_button1); ac++; X XtSetArg (al[ac], XmNcancelButton,but_close); ac++; X XtSetArg (al[ac], XmNwidth, 600); ac++; X XtSetValues (find_dlg, al, ac); X X /* create input area with the text fields */ X X input_area = utility->create_rc_area (find_dlg, "inputArea", XmVERTICAL, X XmALIGNMENT_BEGINNING); X utility->attach (input_area, AtForm, button_area, AtForm, NULL); X X find_label = utility->create_label (input_area, "Replace"); X ac=0; X find_text = XmCreateText (input_area, "findText", al, ac); X XtManageChild (find_text); X X replace_label = utility->create_label (input_area, "With"); X ac=0; X replace_text = XmCreateText (input_area, "replaceText", al, ac); X XtManageChild (replace_text); X X /* create button area with the "insert" buttons for specials */ X X insert_area = utility->create_rc_area (find_dlg, "buttonArea", X XmHORIZONTAL, XmALIGNMENT_BEGINNING); X utility->attach (insert_area, AtForm, NULL, input_area, NULL); X X ac=0; X XtSetArg (al[ac], XmNpacking, XmPACK_TIGHT); ac++; X XtSetValues (insert_area, al, ac); X X ins_label = utility->create_label (insert_area, "Insert:"); X but_ins_lf = utility->create_button (insert_area, "LineBreakButton", X find_dlg_cb, 4, this); X but_ins_tab = utility->create_button (insert_area, "TabButton", X find_dlg_cb, 5, this); X X /* create button area with the toggle buttons for options */ X X toggle_area = utility->create_rc_area (find_dlg, "toggleArea", XmVERTICAL, X XmALIGNMENT_BEGINNING); X utility->attach (toggle_area, AtForm, NULL, but_ins_lf, AtForm); X X ac=0; X but_case = XmCreateToggleButtonGadget (toggle_area, "caseButton", al, ac); X XtManageChild (but_case); X X ac=0; X but_word = XmCreateToggleButtonGadget (toggle_area, "wordButton", al, ac); X XtManageChild (but_word); X X ac=0; X but_direction = XmCreateToggleButtonGadget (toggle_area, "directionButton", al, ac); X XtManageChild (but_direction); X X which_dlg = ReplaceDialog; X} X X// ------------------------------------------------------------------------- X// make_find_dialog: Make sure the dialog is the find version now. X// ------------------------------------------------------------------------- X Xvoid FINDER::make_find_dialog (Boolean backw) X{ X int ac; X Arg al[10]; X X if (which_dlg != FindDialog) { X utility->set_label (find_label, "Find:"); X utility->set_label (but_button1, "Find Forward"); X utility->set_label (but_button2, "Find Backward"); X XtUnmanageChild (replace_label); X XtUnmanageChild (replace_text); X XtUnmanageChild (but_direction); X XtUnmanageChild (but_repl_all); X ac=0; X XtSetArg (al[ac], XmNdialogTitle, find_title); ac++; X XtSetArg (al[ac], XmNwidth, 600); ac++; X XtSetArg (al[ac], XmNx, 10); ac++; X XtSetArg (al[ac], XmNy, 30); ac++; X XtSetValues (find_dlg, al, ac); X X which_dlg = FindDialog; X } X utility->set_sensitive (but_button2, True); X ac=0; X if (backw) { X XtSetArg (al[ac], XmNdefaultButton,but_button2); ac++; X } X else { X XtSetArg (al[ac], XmNdefaultButton,but_button1); ac++; X } X XtSetValues (find_dlg, al, ac); X} X X// ------------------------------------------------------------------------- X// make_replace_dialog: Make sure the dialog is the replace version now. X// ------------------------------------------------------------------------- X Xvoid FINDER::make_replace_dialog () X{ X int ac; X Arg al[10]; X X if (which_dlg != ReplaceDialog) { X utility->set_label (find_label, "Replace:"); X utility->set_label (but_button1, "Find Next"); X utility->set_label (but_button2, "Replace"); X XtManageChild (replace_label); X XtManageChild (replace_text); X XtManageChild (but_direction); X XtManageChild (but_repl_all); X ac=0; X XtSetArg (al[ac], XmNdialogTitle, replace_title); ac++; X XtSetArg (al[ac], XmNwidth, 600); ac++; X XtSetValues (find_dlg, al, ac); X X which_dlg = ReplaceDialog; X } X utility->set_sensitive (but_button2, False); X ac=0; X XtSetArg (al[ac], XmNdefaultButton,but_button1); ac++; X XtSetValues (find_dlg, al, ac); X} SHAR_EOF echo 'File Red/Red/finder.cc is complete' && $shar_touch -am 0512222696 'Red/Red/finder.cc' && chmod 0640 'Red/Red/finder.cc' || echo 'restore of Red/Red/finder.cc failed' shar_count="`wc -c < 'Red/Red/finder.cc'`" test 15088 -eq "$shar_count" || echo "Red/Red/finder.cc: original size 15088, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/info.cc ============== if test -f 'Red/Red/info.cc' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/info.cc (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/info.cc (binary)' sed 's/^X//' << 'SHAR_EOF' > _sharuue.tmp && Xbegin 600 Red/Red/info.cc XM(VEN8VQU9&4@/'-T2!W;W)K('=H96X@=&AE('=I9&=E="!I2`H;&EN93$L(&QN,2P@,C`P*3L*("!S=')N8W!Y XM("AL:6YE,BP@;&XR+"`R,#`I.PH@(&1I2!A(&UEPH@('-T2`H;&EN93(L(&QN,BP@,C`P*3L*("!S:&]W("@I.PI]"@HO+R`M XM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM XM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM"B\O(&EN=%]M97-S86=E.B!, XM:6ME(&UEPH@(&UEPH@('-T2`H;&EN93$L("(B XM*3L*("!S=')C<'D@*&QI;F4R+"`B(BD["B`@97)A2!T XM:&4@8W5R2P@=VEN9&]W+"!G8RP@ XM,RP@9F]N=&%S8V5N="LQ+"!L:6YE,2P@2`](%1R=64["GT*"@HO+R`M+2TM+2TM+2TM+2TM+2TM+2TM+2TM XM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM XM+2TM+2TM"B\O("!EPH@(&EN="!F;W)E9W)O=6YD+"!B XM86-K9W)O=6YD.PH@(%A'0U9A;'5E _sharnew.tmp echo 'x - extracting Red/Red/finder.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/finder.h' && X#ifndef _FINDER_H X#define _FINDER_H X X// ============================================================================ X// X// Class name: FINDER X// X// Author: M. Koelling 1995 X// X// Description: X// X// FINDER is part of the Blue Language integrated environment and Red. X// X// FINDER implements the Find & Replace functions within Red, the editor X// in Blue. It manages the Find and Replace dialog and calls the X// appropriate find functions in the buffer. X// X// The finder is a separate object from the editor to allow the "find X// again" function to be used across different editors. It holds all the X// information about the previous find operation (pattern, case sensitive X// flag, whole word flag, ...) X// X// ============================================================================ X X#include X X#include "editor.h" X Xenum DialogType { FindDialog, ReplaceDialog }; X Xclass FINDER { X X friend void find_dlg_cb (Widget w, XtPointer button, XtPointer call_data); X X public: X FINDER (Widget prnt); X ~FINDER (); X X void show_dialog (Boolean show_replace, // show replace or find dialog X EDITOR* ed, // the performing editor X Boolean backw); // (backw: for find only) X X void get_find_info ( // return info about current find X char*& search_pattern, // parameters (for find_again) X SearchDir& direction, X Boolean& case_matters, X Boolean& whole_word); X X void set_find_string (char* str); // define the string for the next find X X X private: X X void button1 (); // button 1 - can be find fwd / find next X void button2 (); // button 2 - can be find bck / replace X void replace_all (); X void close_dlg (); X void insert_special (char ch); // insert a special char (LF, TAB) X // into search pattern X void find (SearchDir direction); // called when dialog is "find" X void find_next (); // called when dialog is "replace" X void replace (); // called when dialog is "replace" X X void get_search_values (); // read the input from the dialog X void get_replace_pattern (); // read replace pattern from dialog X X void create_dialog (); // create the dialog initially X void make_find_dialog (Boolean backw); // turn into find dialog X void make_replace_dialog (); // turn into replace dialog X X // variables: X X Widget parent; X EDITOR* editor; // the editor which opened the dialog X X DialogType which_dlg; // indicates find or replace X char* pattern; X char* replace_pattern; X Boolean case_sens, word; X SearchDir dir; X X Widget find_dlg; // The dialog for find and replace X Widget but_case, but_word, but_direction; X Widget find_text, replace_text, find_label, replace_label; X Widget but_button1, but_button2, but_repl_all, but_help, but_close; X X XmString find_title; // title for find dialog X XmString replace_title; // title for replace dialog X X const unsigned char NLChar; // the character for displaying NewLine X const unsigned char TABChar; // the character for displaying Tab X}; X X#endif SHAR_EOF $shar_touch -am 0512222696 'Red/Red/finder.h' && chmod 0640 'Red/Red/finder.h' || echo 'restore of Red/Red/finder.h failed' shar_count="`wc -c < 'Red/Red/finder.h'`" test 3029 -eq "$shar_count" || echo "Red/Red/finder.h: original size 3029, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/func-list ============== if test -f 'Red/Red/func-list' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/func-list (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/func-list (binary)' sed 's/^X//' << 'SHAR_EOF' > _sharuue.tmp && Xbegin 600 Red/Red/func-list XM"@I%1$E424Y'.@HM+2TM+2TM+0H)'1?;&EN92P)"0EP XM;&%I;BP@6$M?1&]W;@H)<')E=FEO=7,M;&EN90D).CIP'1? XM<&%G92P)"0EP;&%I;BP@6$M?4&%G95]$;W=N"@EP'0).CIB96=I;FYI;F=?;V9?=&5X="P@ XM"0EP;&%I;BP@6$M?2&]M90H)96YD+6]F+71E>'0)"3HZ96YD7V]F7W1E>'0L XM"0D)<&QA:6XL(%A+7T5N9`H*34E30RX*+2TM+2T*"7)E9&ES<&QA>0D).CIR XM961I0H)<&%S=&4* X` Xend SHAR_EOF echo 'uudecoding file Red/Red/func-list' && uudecode _sharuue.tmp < _sharuue.tmp && rm -f _sharuue.tmp && $shar_touch -am 0512222696 'Red/Red/func-list' && chmod 0640 'Red/Red/func-list' || echo 'restore of Red/Red/func-list failed' shar_count="`wc -c < 'Red/Red/func-list'`" test 1502 -eq "$shar_count" || echo "Red/Red/func-list: original size 1502, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/function.cc ============== if test -f 'Red/Red/function.cc' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/function.cc (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/function.cc (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/function.cc' && X#include "function.h" X XFUNCTION::FUNCTION () X{ X functionName = NULL; X helpString = NULL; X} X XFUNCTION::~FUNCTION () X{ X XmStringFree (functionName); X XmStringFree (helpString); X} X X// ------------------------------------------------------------------------- X Xvoid FUNCTION::define (char *name, CodePtr func, char *help) X{ X if (name) X functionName = XmStringCreateSimple (name); X code = func; X if (help) X helpString = XmStringCreateLtoR (help, XmSTRING_DEFAULT_CHARSET); X} SHAR_EOF $shar_touch -am 0512222696 'Red/Red/function.cc' && chmod 0640 'Red/Red/function.cc' || echo 'restore of Red/Red/function.cc failed' shar_count="`wc -c < 'Red/Red/function.cc'`" test 482 -eq "$shar_count" || echo "Red/Red/function.cc: original size 482, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/function.h ============== if test -f 'Red/Red/function.h' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/function.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/function.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/function.h' && X#ifndef _FUNCTION_H X#define _FUNCTION_H X X#include "../Utility/types.h" X Xclass FUNCTION { X X public: X FUNCTION (); X ~FUNCTION (); X X void define (char *name, // define details of this function X CodePtr func, X char *help); X X // VARIABLES (as always: READ ONLY!) X X XmString functionName; X XmString helpString; X CodePtr code; X}; X X#endif SHAR_EOF $shar_touch -am 0512222696 'Red/Red/function.h' && chmod 0640 'Red/Red/function.h' || echo 'restore of Red/Red/function.h failed' shar_count="`wc -c < 'Red/Red/function.h'`" test 356 -eq "$shar_count" || echo "Red/Red/function.h: original size 356, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/info.h ============== if test -f 'Red/Red/info.h' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/info.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/info.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/info.h' && X#ifndef _INFO_H X#define _INFO_H X X// ============================================================================ X// X// Class name: INFO X// X// Author: M. Koelling 1995 X// X// Description: X// X// The class INFO is part of the Blue Editor. It manages the info area X// (the square at the bottom) in the editor main window. This class (and X// therefor the info area) can be used to display messages and warnings. X// X// ============================================================================ X X#include X#include X Xclass INFO { X X public: X INFO (XFontStruct* infofont); X X void init (Widget draw_area, // be sure to call init WHILE THE X char *ln1, // widget is visible on screen! X char *ln2); X X void message (char *ln1, // print a two lined text message X char *ln1a, // into info area X char *ln2); X X void int_message (int i, // print number and text into line 1, X char *ln1, // second text into line 2 X char *ln2); X X void message_int (char *ln1, // print text and number into line 1, X int i, // second text into line 2 X char *ln2); X X void warning (char *ln1, // print message into info area and X char *ln2); // ring bell X X void clear (); // clear info area logically X X void expose (); X X private: X void show (); // show current text on screen X void erase (); // erase the info area on screen X void setup_gc (Widget da); X X char line1[200]; // contents of the two text lines X char line2[200]; X X const unsigned char LineBreak; // the character for displaying NewLine X X XFontStruct* font; // font used for display of text X X Boolean dirty; // True if there is text in the info area X X GC gc; X Display *display; X Window window; X X Boolean first_init; X int fontascent; X int fontheight; X}; X X#endif SHAR_EOF $shar_touch -am 0512222696 'Red/Red/info.h' && chmod 0640 'Red/Red/info.h' || echo 'restore of Red/Red/info.h failed' shar_count="`wc -c < 'Red/Red/info.h'`" test 1857 -eq "$shar_count" || echo "Red/Red/info.h: original size 1857, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/keymap.cc ============== if test -f 'Red/Red/keymap.cc' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/keymap.cc (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/keymap.cc (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/keymap.cc' && X#include X#include X X#include "keymap.h" X#include "function.h" X#include "../Utility/debug.h" X X// ========================== interface functions ========================== X X// ------------------------------------------------------------------------- X// KEYMAP: create the keymap and initialise to invalid entries. X// ------------------------------------------------------------------------- X XKEYMAP::KEYMAP (char* name) X{ X prefix = name; // the prefix for key strings in this keymap X search_idx = -1; X} X X// ------------------------------------------------------------------------- X// init: Clear all key bindings (set all to NOT_BOUND). X// ------------------------------------------------------------------------- X Xvoid KEYMAP::init () X{ X int i; X X for (i=0; i=-1) && (search_idx < NR_OF_KEYS)); X search_idx++; X X while ((search_idx < NR_OF_KEYS) && (binding[search_idx] != func)) X search_idx++; X X if (search_idx == NR_OF_KEYS) X return XK_VoidSymbol; X else X return index_to_sym (search_idx); X} X X// --------------------------------------------------------------------------- X// key_string: Convert a key index into its string representation. The string X// is allocated here. X// --------------------------------------------------------------------------- X Xchar* KEYMAP::key_string (KeySym key) X{ X char* str; X X str = new char[30]; X strcpy (str, prefix); X strcat (str, XKeysymToString (key)); X return str; X} X X// --------------------------------------------------------------------------- X// save_to_file: Save this keymap to "file". The file is already open. X// --------------------------------------------------------------------------- X Xvoid KEYMAP::save_to_file (ofstream& file) X{ X int i; X char ch; X X for (i=0; i= UFBackDeleteUntab) X binding[i] = (UserFuncId)(binding[i] + 1); X if (binding[i] >= UFHalfTab) X binding[i] = (UserFuncId)(binding[i] + 1); X if (binding[i] >= UFShiftLeft) X binding[i] = (UserFuncId)(binding[i] + 2); X } X assert (binding[i] < UNKNOWN_KEY); X } X} X X X// =========================== private functions =========================== X X// ------------------------------------------------------------------------- X// sym_to_index: first (internal) mapping. Map the key symbol to an index X// in the bindings array. For details about internal indexes see X// keymap.h. X// ------------------------------------------------------------------------- X Xint KEYMAP::sym_to_index (KeySym key) X{ X// for most ascii chars the last byte is the index X X if (key >= XK_space && key <= XK_quoteleft) X return (key & 255); X X// some ranges of keys are mapped to ranges of indexes X X if (key >= XK_a && key <= XK_z) // a - z mapped to upper case X return ((key & 255) - 32); X X if (key >= XK_Home && key <= XK_Begin) // cursor motion - index 7 ff X return (key - XK_Home + 7); X X if (key >= XK_KP_Multiply && key <= XK_KP_9) // keypad - index 16 ff X return (key - XK_KP_Multiply + 16); X X if (key >= XK_F1 && key <= XK_F35) // function keys - index 105 ff X return (key - XK_F1 + 105); X X// now some individual keys X X switch (key) { X X case XK_BackSpace: return 0; X case XK_Tab: return 1; X case XK_Linefeed: return 2; X case XK_Return: return 3; X case XK_Escape: return 4; X case XK_KP_Enter: return 5; X case XK_Delete: return 6; X case XK_braceleft: return 97; X case XK_bar: return 98; X case XK_braceright: return 99; X case XK_asciitilde: return 100; X case XK_Select: return 101; X case XK_Print: return 102; X case XK_Execute: return 103; X case XK_Insert: return 104; X X default: return -1; X } X} X X// ------------------------------------------------------------------------- X// index_to_sym: internal mapping. Map the key index to an symbol. X// For details about internal indexes see keymap.h. X// ------------------------------------------------------------------------- X XKeySym KEYMAP::index_to_sym (int idx) X{ X X// for most ascii chars the index is the same as the Sym X X if (idx >= 32 && idx <= 96) // space - quoteleft (incl. a - z) X return (idx); X X// some ranges of idxs are mapped to ranges of indexes X X if (idx >= 07 && idx <= 15) // cursor motion - index 7 ff X return (idx - 7 + XK_Home); X X if (idx >= 16 && idx <= 31) // keypad - index 16 ff X return (idx - 16 + XK_KP_Multiply); X X if (idx >= 105 && idx <= 139) // function keys - index 105 ff X return (idx - 105 + XK_F1); X X// now some individual idxs X X switch (idx) { X X case 0: return XK_BackSpace; X case 1: return XK_Tab; X case 2: return XK_Linefeed; X case 3: return XK_Return; X case 4: return XK_Escape; X case 5: return XK_KP_Enter; X case 6: return XK_Delete; X X case 97: return XK_braceleft; X case 98: return XK_bar; X case 99: return XK_braceright; X case 100: return XK_asciitilde; X X case 101: return XK_Select; X case 102: return XK_Print; X case 103: return XK_Execute; X case 104: return XK_Insert; X } X X assert (False); // make sure a legal value was found X return XK_Escape; // just to avoid a warning... X} X SHAR_EOF $shar_touch -am 0512223996 'Red/Red/keymap.cc' && chmod 0640 'Red/Red/keymap.cc' || echo 'restore of Red/Red/keymap.cc failed' shar_count="`wc -c < 'Red/Red/keymap.cc'`" test 7705 -eq "$shar_count" || echo "Red/Red/keymap.cc: original size 7705, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/keymap.h ============== if test -f 'Red/Red/keymap.h' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/keymap.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/keymap.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/keymap.h' && X#ifndef _KEYMAP_H X#define _KEYMAP_H X X// --------------------------------------------------------------------------- X// class KEYMAP X// X// A KEYMAP is an array of pointers to functions. Each keypress will be X// mapped to an index in this array. We have separate keymaps for each valid X// modifier combination, so inside the keymap we don't care about modifiers X// any more. X// X// Key symbols (keysyms) are 16 bit numbers. They are here mapped onto an X// array of 166 entries (since we recognise 166 different keys). The mapping X// is as follows: X// X// keysym value hex / dec index X// ------------------------------------ X// BackSpace FF08 00 00 X// Tab FF09 01 01 X// Linefeed FF0A 02 02 X// Return FF0D 03 03 X// Escape FF1B 04 04 X// KP_Enter FF8D 05 05 X// Delete FFFF 06 06 X// X// Home FF50 07 07 X// ... ... .. .. X// Begin FF58 0F 15 X// X// KP_Mult FFAA 10 16 *** start of printables X// ... ... .. .. X// KP_9 FFB9 1F 31 X// X// space 0020 20 32 X// ... ... .. .. X// quoteleft 0060 60 96 X// X// a 0061 41 65 *** lower case mapped onto same X// ... ... .. .. *** indices as upper case X// z 007A 5A 90 X// X// braceleft 007B 61 97 X// bar ... .. .. X// braceright X// asciitilde 007E 64 100 *** end of printables X// X// Select FF60 65 101 X// Print ... .. .. X// Execute X// Insert FF63 68 104 X// X// F1 FFBE 69 105 X// ... .. X// F35 FFE0 8B 139 X// X// So the mapping takes place in two steps: first the keysym is mapped onto X// an array index, then it is mapped onto a function associated with that X// index. X// X// --------------------------------------------------------------------------- X X// for reading from file: X#include X X#include "../Utility/types.h" X#include "function.h" X X// IDs for each user function X Xenum UserFuncId { X UFNewLine, UFOpenLine, UFDeleteChar, UFBackDeleteChar, UFBackDeleteUntab, X UFTabToTabStop, UFHalfTab, X UFIndent, UFNewLineIndent, UFCutWord, UFCutToEOWord, UFCutLine, UFCutToEOLine, X UFCutRegion, UFCut, UFPaste, UFSelectWord, UFSelectLine, UFSelectRegion, X UFShiftLeft, UFShiftRight, X X UFForwardChar, UFBackwardChar, UFForwardWord, UFBackwardWord, UFEndOfLine, X UFBegOfLine, UFNextLine, UFPrevLine, UFScrollLineDown, UFScrollLineUp, X UFScrollHPDown, UFScrollHPUp, UFPrevPage, UFNextPage, UFBegOfText, X UFEndOfText, UFSwapCursorMark, X X UFNew, UFOpen, UFSave, UFSaveAs, UFRevert, UFClose, UFPrint, X X UFPreferences, UFKeyBindings, UFEditToolb, UFSetFonts, UFSetColours, X X UFDescribeKey, UFShowManual, X X UFUndo, UFFind, UFFindBackward, UFFindNext, UFFindNextRev, UFReplace, X UFSetMark, UFGotoLine, UFShowLine, UFDefMacro, UFEndMacro, UFRunMacro, X UFInterface, UFRedisplay, UFBlueNewRout, UFStatus, X X UFCompile, UFGotoError, UFSetBreak, UFClearBreak, UFPrintVar, UFWatchVar, X UFStep, UFStepInto, UFContinue, UFTerminate, X X UFSelfInsert, X X NR_OF_USERFUNC, NOT_BOUND, UNKNOWN_KEY X}; X Xclass KEYMAP { X X const int NR_OF_KEYS = 140; X const int FIRST_PRINTABLE = 16; X const int LAST_PRINTABLE = 100; X X public: X KEYMAP (char *name); X X // Create a keymap with name "name" and no bindings. X X X void init (); X X // Clear all key bindings (set all to NOT_BOUND). X X X Boolean bind (KeySym key, UserFuncId func); X X // Insert a binding from key to func. The function is defined by X // its index in the user function table. X X X void bind_printables (UserFuncId func); X X // Insert a binding for all printable keys to function "func". X X X UserFuncId map (KeySym key); X X // Return the function binding for key. If it is not bound, the value will X // be NOT_BOUND. If it is an unknown key, the value will be UNKNOWN_KEY. X X X void init_search (); X X // Init a search for keys that map to a particular function. X X X KeySym search_key (UserFuncId func); X X // Search for a key that is bound to function "func". If none is found, X // XK_VoidSymbol is returned. X X X char* key_string (KeySym key); X X // Convert a key index into its string representation. X X X void save_to_file (ofstream& file); X X void read_from_file (ifstream& file, Boolean convert); X X private: X int sym_to_index (KeySym key); // internal mapping: keysym to index X KeySym index_to_sym (int idx); // internal mapping: index to keysym X X char* prefix; // This map's prefix for key strings X X UserFuncId binding[NR_OF_KEYS]; // binding information for every key X X int search_idx; X}; X X#endif SHAR_EOF $shar_touch -am 0512222696 'Red/Red/keymap.h' && chmod 0640 'Red/Red/keymap.h' || echo 'restore of Red/Red/keymap.h failed' shar_count="`wc -c < 'Red/Red/keymap.h'`" test 4521 -eq "$shar_count" || echo "Red/Red/keymap.h: original size 4521, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/line.cc ============== if test -f 'Red/Red/line.cc' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/line.cc (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/line.cc (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/line.cc' && X// ============================================================================ X// File: line.cc -mik- 1995 X// X// Implementation of class LINE. See line.h for description. X// Line is part of the Blue programming environment. X// ============================================================================ X X#include X X#include "buffer.h" X#include "../Utility/stdfunc.h" X#include "../Utility/debug.h" X X//---------------------------------------------------------------------------- X// LINE: Line creator. Buffersize is the initial size of the physical buffer X// to hold the text of the line. For endmark, this is 0, resulting in X// no buffer being allocated (text == NULL). For all other lines, this X// MUST be >0 (since this is used as a check to recognise endmark). X// str is the initial line text, len is the logical line length. X//---------------------------------------------------------------------------- X XLINE::LINE (int buffersize, char *str, int len) X{ X bufsize = buffersize; X length = len; X tag = NoLineTag; X select = NoSelection; X if (buffersize > 0) { X text = new char [buffersize]; X if (length>0) X bcopy (str, text, length); X } X else X text = NULL; // marks endmark X} X X//---------------------------------------------------------------------------- X//---------------------------------------------------------------------------- X XLINE::~LINE () X{ X if (text != NULL) X delete [] text; X} X X//---------------------------------------------------------------------------- X// insert: insert a character into the line (or at end of line). If the X// character buffer is full, another buffer is allocated. Then the X// character is inserted or appended. X//---------------------------------------------------------------------------- X Xvoid LINE::insert (char ch, int index) X{ X assert (index<=length); X X check_buffer (1); // ensure buffer is large enough X X if (index=idx1); X X bcopy (&text[idx2], &text[idx1], length-idx2); X length = length - (idx2-idx1); X} X X//---------------------------------------------------------------------------- X// check_buffer: Make sure buffer is big enough to insert 'new_chars' X// characters. If it is not, allocate a new (bigger) buffer. X//---------------------------------------------------------------------------- X Xvoid LINE::check_buffer (int new_chars) X{ X char* oldtext; X X if (length+new_chars > bufsize) { // need larger buffer X if (new_chars>40) X bufsize+=new_chars; X else X bufsize+=40; // add at least 40 characters X oldtext = text; X text = new char [bufsize]; X bcopy (oldtext, text, length); X delete [] oldtext; X } X} SHAR_EOF $shar_touch -am 0512222696 'Red/Red/line.cc' && chmod 0640 'Red/Red/line.cc' || echo 'restore of Red/Red/line.cc failed' shar_count="`wc -c < 'Red/Red/line.cc'`" test 5538 -eq "$shar_count" || echo "Red/Red/line.cc: original size 5538, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/line.h ============== if test -f 'Red/Red/line.h' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/line.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/line.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/line.h' && X#ifndef _LINE_H X#define _LINE_H X X// ============================================================================ X// X// Class name: LINE X// X// Author: M. Koelling 1995 X// X// Description: X// X// LINE is one line of text in the buffer. The text is stored as a block X// of characters and a length field. There is NO null byte at the end. X// The line has links to join in a doubly linked list and a mark field. X// X// ============================================================================ X Xenum LineTag { X NoLineTag, ErrorLineTag, BreakLineTag, ExecLineTag, ExecBreakLineTag X}; Xenum SelectStatus { X NoSelection, SelectionStart, InSelection, SelectionEnd, ContainsSelection X }; X Xclass LINE { X X public: X LINE (int buffersize, char *str, int len); X ~LINE (); X X void insert (char ch, int index); // insert a character X void insert_string (char* str, // insert a string X int len, X int index); X void remove (int index); // delete a character X void append (char *str, int len); // append a string X void append_char (char ch); // append a character X void delete_tail (int index); // delete from index to end X void delete_head (int index); // delete from beginning to index X void delete_part (int idx1, // delete from idx1 to idx2 X int idx2); X LINE *next; // Link to next line X LINE *prev; // Link to previous line X int length; // Logical length of line X char *text; // Pointer to line buffer X LineTag tag; // Tag of line X SelectStatus select; // Indicates whether line is selected X X private: X void check_buffer (int new_chars); X X int bufsize; // buffer size (physical length) X}; X X#endif SHAR_EOF $shar_touch -am 0512222696 'Red/Red/line.h' && chmod 0640 'Red/Red/line.h' || echo 'restore of Red/Red/line.h failed' shar_count="`wc -c < 'Red/Red/line.h'`" test 1670 -eq "$shar_count" || echo "Red/Red/line.h: original size 1670, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/red.cc ============== if test -f 'Red/Red/red.cc' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/red.cc (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/red.cc (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/red.cc' && X// ============================================================================ X// File: red.cc -mik- 1995 X// X// Implementation of class RED. See red.h for description. X// Red is part of the Blue programming environment. X// ============================================================================ X X// the following three are all for getting the home directory X// (getuid and getpwuid) X#include X#include X#include X X// for reading prefs: X#include X X#include X#include X X#include "red.h" X#include "editor.h" X#include "defines.h" X#include "../Utility/utility.h" X#include "../Utility/debug.h" X#include "../Utility/question_dlg.h" X#include "../Utility/messages.h" X X// this is the GLOBAL Red object XRED *red; X X#include "red_callbacks.i" X X// ------------------------------------------------------------------------- X// RED: Initialisation of instance variables. The parameters must be X// stored - we need them to pass them on to every single editor later. X// The list of open editors is empty initially. X// ------------------------------------------------------------------------- X XRED::RED (Widget toplev, ApplicationData *resources) X{ X toplevel = toplev; X rsrc = resources; X editor_list = new LIST (); X saving_editor = NULL; // used while saving an editor X closing_editor = NULL; // used while closing an editor X opening_editor = NULL; // used while opening a file X X userfunc = new USERFUNC (toplevel); X finder = new FINDER (toplevel); X paste_buffer = NULL; X X read_prefs (); X} X X// ------------------------------------------------------------------------- X// ~RED: Destructor - delete all the data strutures held by this class, X// that is the editors currently open and the user functions. X// ------------------------------------------------------------------------- X XRED::~RED () X{ X delete editor_list; X delete userfunc; X} X X#ifdef RED_ONLY X #include "red_file.i" X X // ------------------------------------------------------------------------- X // edit_file: Create a new editor instance showing the file 'filename'. X // This function gets finally called after the user chose "open", X // selected a file and clicked OK. X // ------------------------------------------------------------------------- X X void RED::edit_file (char *filename, Boolean iconic) X { X (void) open_editor (NULL, filename, True, iconic, NULL); X } X X#else X X // ------------------------------------------------------------------------- X // edit_class: Edit source code of a class. X // ------------------------------------------------------------------------- X X EDITOR *RED::edit_class (ICLASS *cl, char *filename, Boolean compiled, X LIST* breakpoints) X { X return open_editor (cl, filename, compiled, False, breakpoints); X } X X // ------------------------------------------------------------------------- X // set_debug: Show/hide (depending on arg) the debug buttons in all the X // editor windows. X // ------------------------------------------------------------------------- X X void RED::set_debug (Boolean arg) X { X EDITOR *editor; X X editor_list->init_scan (ScanForward); X while ((editor = (EDITOR *)(editor_list->next_element ()))) X editor->set_debug (arg); X editor_list->end_scan (); X } X X#endif X X X// ------------------------------------------------------------------------- X// close_request: Start a "close editor" action. That is: check whether X// it has been changed; if so, ask for save. If not, go on to real X// close straight away. X// ------------------------------------------------------------------------- X Xvoid RED::close_request (EDITOR *editor, Widget edit_win, Boolean changed) X{ X closing_editor = editor; X if (changed) X messages->show_question (edit_win, QuSaveChanges, X RED__close_editor, editor); X else X close_editor (False); X} X X// ------------------------------------------------------------------------- X// close_editor: The editor is about to be closed. If "save" is true, the X// buffer should be saved first. So save it and then proceed. Then X// take it from the used editors list and delete it. X// ------------------------------------------------------------------------- X Xvoid RED::close_editor (Boolean save) X{ X assert (closing_editor); // must be set! X X if (save) X closing_editor->save (); X X // if the save operation results in a file selection dialog being opened, X // the save is not completed on return. This is indicated by the X // "saving_editor" variable being not NULL. In that case just leave X // "closing_editor" not-NULL as a flag and it will be closed after the save. X X if (saving_editor == NULL) { X editor_list->remove (closing_editor); X delete closing_editor; X closing_editor = NULL; X X #ifdef RED_ONLY X if (editor_list->num_elements() == 0) X exit (0); // last editor closed -- exit X #endif X } X} X X// ------------------------------------------------------------------------- X// beep_on: True, if beep on warning is switched on. X// ------------------------------------------------------------------------- X XBoolean RED::beep_on () X{ X return beep_warning; X} X X// ------------------------------------------------------------------------- X// backup_on: True, if automatic backup is switched on. X// ------------------------------------------------------------------------- X XBoolean RED::backup_on () X{ X return make_backup; X} X X// ------------------------------------------------------------------------- X// append_nl_on: True, if automatic appending of newline is switched on. X// ------------------------------------------------------------------------- X XBoolean RED::append_nl_on () X{ X return append_newline; X} X X#include "red_dlg.i" X X// ========================================================================= X// private routines X// ========================================================================= X X// ------------------------------------------------------------------------- X// open_editor: Create a new editor instance showing the source code of X// file 'filename'. This function gets finally called after the user X// chose "open", selected a file and clicked OK. It also gets called X// by the project class if a class is to be displayed. X// The new editor is returned if the open was successful, NULL X// otherwise. X// ------------------------------------------------------------------------- X XEDITOR *RED::open_editor (ICLASS *cl, char *filename, X Boolean compiled, Boolean iconic, LIST* breakpoints) X{ X EDITOR *new_ed; X X new_ed = new EDITOR (rsrc); X editor_list->append (new_ed); X if (new_ed->open (toplevel, cl, filename, breakpoints, show_toolbar, X compiled, iconic)) // open editor X return new_ed; X else { X close_request (new_ed, NULL, False); // close if not successful X return NULL; X } X} X X// ------------------------------------------------------------------------- X// read_prefs: Read the preferences file. X// ------------------------------------------------------------------------- X Xvoid RED::read_prefs () X{ X char filename[100]; X char version[10]; X passwd *pw; X Boolean done = False; X Boolean old_version = False; X X pw = getpwuid (getuid ()); X strncpy (filename, pw->pw_dir, 90); X strcat (filename, PREF_NAME); X X ifstream pref(filename); X if (pref) { // pref file does exist X pref.get (version, 9, '\n'); X X// for the moment: other versions don't matter (there is only one) X// if (strcmp (version, RED_VERSION)) X// messages->show_error (toplevel, ErrReadPrefs); X// else { X pref.get (version[9]); // skip '\n' X pref.get (show_toolbar); X pref.get (beep_warning); X pref.get (make_backup); X pref.get (append_newline); X if (strcmp (version, RED_VERSION)) X old_version = True; X done = True; X// } X pref.close (); X } X if (old_version) { // If the pref version is old... X append_newline = True; // set append to true X write_prefs (); X } X X if (!done) { // -> use defaults X show_toolbar = True; X beep_warning = True; X make_backup = True; X append_newline = True; X } X} X X// ------------------------------------------------------------------------- X// write_prefs: Write the preferences file. X// ------------------------------------------------------------------------- X Xvoid RED::write_prefs () X{ X char filename[100]; X passwd *pw; X X pw = getpwuid (getuid ()); X strncpy (filename, pw->pw_dir, 90); X strcat (filename, PREF_NAME); X X ofstream pref(filename); X pref << RED_VERSION << '\n'; X pref.put (show_toolbar); X pref.put (beep_warning); X pref.put (make_backup); X pref.put (append_newline); X pref.close (); X} SHAR_EOF $shar_touch -am 0512222696 'Red/Red/red.cc' && chmod 0640 'Red/Red/red.cc' || echo 'restore of Red/Red/red.cc failed' shar_count="`wc -c < 'Red/Red/red.cc'`" test 8683 -eq "$shar_count" || echo "Red/Red/red.cc: original size 8683, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/red.h ============== if test -f 'Red/Red/red.h' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/red.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/red.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/red.h' && X#ifndef _RED_H X#define _RED_H X X// ============================================================================ X// X// Class name: RED X// X// Author: M. Koelling 1995 X// X// Description: X// X// RED is the editor of the Blue Language integrated environment. X// It can be compiled as an integrated part of Blue, or as a X// stand-alone version. X// X// ... (to be continued) X// X// RED implements the common part of the multiple edit windows, that the X// user can open. All the data structures common to all edit windows are X// created and stored here. They are: the list of user functions and the X// key maps. They are created here once at program startup and then X// passed to every editor as it is opened. (Note: an editor in Red is X// the part of the system that handles editing of a single file in an X// own window. So Red can have several "editors" open.) X// X// ============================================================================ X// VERSION BY DATE DESCRIPTION X// ---------------------------------------------------------------------------- X// 0.1 mik 3/95 First test version X// 0.42 mik 7/95 First version to be tested by other testers. X// Seems functional. X// 0.5 mik 7/95 Undo implemented. Some errors fixed. X// 0.6 mik 8/95 Copy/Paste protocol implemented to copy to/from X// other X applications. X// 0.63 mik 8/95 "open" uses empty buffer if available X// 0.7 mik 10/95 indent and message of the day implemented X// ============================================================================ X X#include X X#include "../Utility/types.h" X#include "../Utility/fs_dialog.h" X#include "../Utility/list.h" X#include "editor.h" X#include "function.h" X#include "keymap.h" X#include "userfunc.h" X#include "finder.h" X#ifndef RED_ONLY X #include "../Project/iclass.h" X#endif X Xtypedef void (EDITOR::*EditorFuncPtr)(Boolean); // pointer to editor function X X Xclass RED { X X friend void RED__end_pref_dialog (Widget w, XtPointer button, X XtPointer call_data); X X friend void RED__close_editor (Widget w, XtPointer dlg, X XtPointer call_data); X X #ifdef RED_ONLY X friend void RED__save_as (Widget w, XtPointer user_data, X XmFileSelectionBoxCallbackStruct *call_data); X X friend void RED__open_file (Widget w, XtPointer user_data, X XmFileSelectionBoxCallbackStruct *callback_data); X #endif X X public: X X RED (Widget toplev, ApplicationData *resources); X ~RED (); // Destructor X X #ifdef RED_ONLY X X // in red_file.i: X X void open_request (EDITOR* editor, // 'Open' from menu X char *dirname); X X void open_file (XmFileSelectionBoxCallbackStruct *callback_data); X // After finishing open-dlg X X void save_as_request (EDITOR* editor, // 'save as' chosen in editor X char *dirname); X X void save_as (XmFileSelectionBoxCallbackStruct *callback_data); X // returned from fs dialog X X void edit_file (char *filename, // Edit file 'filename' X Boolean iconic); X X #else X X EDITOR *edit_class (ICLASS *cl, // Open and return new editor X char *filename, // for class 'cl', with source X Boolean compiled, // in 'filename' X LIST* breakpoints); X X void set_debug (Boolean arg); // Show/hide debug buttons in editors X X #endif X X void close_request (EDITOR* editor, // Requesting to close editor X Widget edit_win, X Boolean changed); X X void close_editor (Boolean save); // Closing editor window X X Boolean beep_on (); // True if beeping is on X Boolean backup_on (); // True if make_backup is on X Boolean append_nl_on (); // True if "append newline" is on X X // in red_dlg.i: X X void show_pref_dialog (Widget parent); X void edit_toolbar (); X void show_font_dialog (); X void show_colour_dialog (); X X // variables: (read-only!!) X X ApplicationData *rsrc; // structure with application resource X // values X USERFUNC* userfunc; // The object defining user functions X FINDER* finder; X char* paste_buffer; X X private: X X EDITOR *open_editor (ICLASS *cl, // Open new editor for file X char *filename, // 'filename' (of class 'cl') X Boolean compiled, X Boolean iconic, X LIST* breakpoints); X X void end_pref_dialog (int button); X X void read_prefs (); // read the prefs file X void write_prefs (); // write the prefs file X X // VARIABLES: X X LIST* editor_list; // List of open editors X X EDITOR* saving_editor; // editor currently performing save_as X EDITOR* closing_editor; // editor currently closing X EDITOR* opening_editor; // editor currently opening X X // preference settings: X Boolean show_toolbar; X Boolean beep_warning; X Boolean make_backup; X Boolean append_newline; X X Widget toplevel; // Top level widget (to open window) X Widget pref_dlg; // preferences dialog X Widget show_TB_button, beep_button, backup_button, newline_button; X}; X Xextern RED *red; // declare the GLOBAL red object X X#endif SHAR_EOF $shar_touch -am 0512222696 'Red/Red/red.h' && chmod 0640 'Red/Red/red.h' || echo 'restore of Red/Red/red.h failed' shar_count="`wc -c < 'Red/Red/red.h'`" test 4959 -eq "$shar_count" || echo "Red/Red/red.h: original size 4959, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/red_callbacks.i ============== if test -f 'Red/Red/red_callbacks.i' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/red_callbacks.i (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/red_callbacks.i (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/red_callbacks.i' && X// ========================================================================= X// X// FILE: red_callbacks.i - part of red.cc -mik- 1995 X// X// This file contains the callbacks for the class RED. X// It is part of the implementation of class RED. X// X// Callbacks C functions called on a user interface event (such as a button X// press). They (unfortunatly) must have a C interface (Motif wants that). X// X// The convention for the Blue implementation is: Callback functions consist X// ONLY of the required call to the desired object function. X// X// Naming Convention: Callback names consist of the class and function X// names of the function they call, separated by a double underscore, X// X// e.g.: CLASS__function_name X// X// ========================================================================= X X// any button in the preferences dialog: X Xvoid RED__end_pref_dialog (Widget w, XtPointer button, XtPointer call_data) X{ X red->end_pref_dialog ((int) button); X} X X// ------------------------------------------------------------------------- X X// Yes or No button in the "Do you want to save" dialog X Xvoid RED__close_editor (Widget w, XtPointer dlg, XtPointer call_data) X{ X EDITOR* editor; X bool yes_no; X X editor = (EDITOR*) messages->close_question (dlg, w, yes_no); X red->close_editor (yes_no); X} X X// ------------------------------------------------------------------------- X#ifdef RED_ONLY X X void RED__save_as (Widget w, XtPointer user_data, X XmFileSelectionBoxCallbackStruct *call_data) X { X red->save_as (call_data); X } X X// ------------------------------------------------------------------------- X void RED__open_file (Widget w, XtPointer user_data, X XmFileSelectionBoxCallbackStruct *call_data) X { X red->open_file (call_data); X } X#endif SHAR_EOF $shar_touch -am 0512222696 'Red/Red/red_callbacks.i' && chmod 0640 'Red/Red/red_callbacks.i' || echo 'restore of Red/Red/red_callbacks.i failed' shar_count="`wc -c < 'Red/Red/red_callbacks.i'`" test 1765 -eq "$shar_count" || echo "Red/Red/red_callbacks.i: original size 1765, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/red_dlg.i ============== if test -f 'Red/Red/red_dlg.i' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/red_dlg.i (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/red_dlg.i (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/red_dlg.i' && X// ------------------------------------------------------------------------- X// show_pref_dialog: X// ------------------------------------------------------------------------- X Xvoid RED::show_pref_dialog (Widget parent) X{ X int ac; X Arg al[10]; X X Widget toggle_area, button_area; X Widget pref_ok, pref_cancel, pref_help; X X /* create a window for the dialog */ X X ac=0; X XtSetArg (al[ac], XmNmwmDecorations, 2 | 8); ac++; // border and title X XtSetArg (al[ac], XmNnoResize, True); ac++; X pref_dlg = XmCreateFormDialog (parent, "DialogPref", al, ac); X X toggle_area = utility->create_rc_area (pref_dlg, "toggleArea", XmVERTICAL, X XmALIGNMENT_BEGINNING); X utility->attach (toggle_area, AtForm, AtForm, AtForm, NULL); X X ac=0; X XtSetArg (al[ac], XmNborderWidth, 1); ac++; X XtSetValues (toggle_area, al, ac); X X // create buttons X show_TB_button = utility->create_toggle (toggle_area, "showTbButton", X show_toolbar, NULL, NULL); X beep_button = utility->create_toggle (toggle_area, "beepButton", X beep_warning, NULL, NULL); X backup_button = utility->create_toggle (toggle_area, "backupButton", X make_backup, NULL, NULL); X newline_button = utility->create_toggle (toggle_area, "newlineButton", X append_newline, NULL, NULL); X X button_area = utility->create_rc_area (pref_dlg, "buttonArea", XmHORIZONTAL, X XmALIGNMENT_CENTER); X utility->attach (button_area, NULL, AtForm, toggle_area, AtForm); X X pref_ok = utility->create_button (button_area, "OkButton", X RED__end_pref_dialog, XmCR_OK, this); X pref_cancel = utility->create_button (button_area, "CancelButton", X RED__end_pref_dialog, XmCR_CANCEL, this); X pref_help = utility->create_button (button_area, "HelpButton", X show_help, HlpPref, this); X X ac=0; X XtSetArg (al[ac], XmNhorizontalSpacing, 20); ac++; X XtSetArg (al[ac], XmNverticalSpacing,20); ac++; X XtSetArg (al[ac], XmNdefaultButton,pref_ok); ac++; X XtSetArg (al[ac], XmNcancelButton,pref_cancel); ac++; X XtSetValues (pref_dlg, al, ac); X X XtManageChild (pref_dlg); X} X X// ------------------------------------------------------------------------- X// end_pref_dialog: The preference dialog has been ended. Should check X// here whether it was the Ok or Cancel button and then do something. X// ------------------------------------------------------------------------- X Xvoid RED::end_pref_dialog (int button) X{ X Boolean toolbar; X EDITOR *editor; X X if (button == XmCR_OK) { X toolbar = utility->read_toggle (show_TB_button); X beep_warning = utility->read_toggle (beep_button); X make_backup = utility->read_toggle (backup_button); X append_newline = utility->read_toggle (newline_button); X X // if toolbar setting changed, call editors to show/hide toolbar X X if (toolbar != show_toolbar) { X editor_list->init_scan (ScanForward); X while ((editor = (EDITOR *)(editor_list->next_element ()))) X editor->show_toolbar (toolbar); X editor_list->end_scan (); X show_toolbar = toolbar; X } X write_prefs (); // write to file X } X X XtDestroyWidget (pref_dlg); X} X X// ------------------------------------------------------------------------- X// edit_toolbar: X// ------------------------------------------------------------------------- X Xvoid RED::edit_toolbar () X{ X messages->show_help (toplevel, HlpNYI); // NYI X} X X// ------------------------------------------------------------------------- X// show_font_dialog: X// ------------------------------------------------------------------------- X Xvoid RED::show_font_dialog () X{ X messages->show_help (toplevel, HlpNYI); X} X X// ------------------------------------------------------------------------- X// show_colour_dialog: X// ------------------------------------------------------------------------- X Xvoid RED::show_colour_dialog () X{ X messages->show_help (toplevel, HlpNYI); X} X SHAR_EOF $shar_touch -am 0512222696 'Red/Red/red_dlg.i' && chmod 0640 'Red/Red/red_dlg.i' || echo 'restore of Red/Red/red_dlg.i failed' shar_count="`wc -c < 'Red/Red/red_dlg.i'`" test 3827 -eq "$shar_count" || echo "Red/Red/red_dlg.i: original size 3827, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/red_file.i ============== if test -f 'Red/Red/red_file.i' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/red_file.i (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/red_file.i (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/red_file.i' && X// =========================================================================== X// X// file: red_file.i -mik-, Apr 95 X// X// red_file.i is part of red.cc and contains impementations for file I/O X// functions. X// X// This file is only used in the stand-alone version of Red. X// X// =========================================================================== X X// ------------------------------------------------------------------------- X// open_request: The 'open' item from the menu was chosen. Show a file X// selection box to let the user choose a file to open. X// ------------------------------------------------------------------------- X Xvoid RED::open_request (EDITOR* editor, char *dirname) X{ X assert (opening_editor == NULL); X opening_editor = editor; X utility->fs_dialog->show (RED__open_file, dirname, false, false); X delete [] dirname; X} X X// ------------------------------------------------------------------------- X// open_file: A button in the open-file-dialog was clicked. Find out X// which button. If it was OK, get the string out of that dialog and X// try to open that file. X// ------------------------------------------------------------------------- X Xvoid RED::open_file (XmFileSelectionBoxCallbackStruct *callback_data) X{ X char *filename; X X utility->fs_dialog->hide (); X X switch (callback_data->reason) { X X case (XmCR_OK): X XmStringGetLtoR (callback_data->value, XmSTRING_DEFAULT_CHARSET, X &filename); X X if (opening_editor) // load into this editor X opening_editor->open (toplevel, NULL, filename, NULL, show_toolbar, X True, False); X else X (void) open_editor (NULL, filename, True, False, NULL); X break; X X default: X break; // nothing to do X } X opening_editor = NULL; X} X X// ------------------------------------------------------------------------- X// save_as_request: An editor has issued a "save_as" (or a save with no X// filename specified). It now requests of Red to initiate a "save-as" X// dialog. The editor is stored (for later) and the file selection X// dialog is shown. When completed (with either OK or Cancel) it will X// call "red->save_as" (see below). The "saving_editor" variable is X// important, since it is used as a flag to check for this dialog while X// closing an editor. X// ------------------------------------------------------------------------- X Xvoid RED::save_as_request (EDITOR* editor, char *dirname) X{ X assert (saving_editor == NULL); // if not, something got screwed up X X saving_editor = editor; X utility->fs_dialog->show (RED__save_as, dirname, false, true); X delete [] dirname; X} X X// ------------------------------------------------------------------------- X// save_as: The file selection dialog for the "save_as" command has been X// completed. "which_button" tells whether it was the OK or Cancel X// button. If it was OK, save the buffer under that new filename. X// If this file selection was popped up while the editor was being X// closed, resume the close operation now. X// ------------------------------------------------------------------------- X Xvoid RED::save_as (XmFileSelectionBoxCallbackStruct *callback_data) X{ X char *filename; X X assert (saving_editor != NULL); X utility->fs_dialog->hide (); X X switch (callback_data->reason) { X X case (XmCR_OK): X XmStringGetLtoR (callback_data->value, XmSTRING_DEFAULT_CHARSET, X &filename); X saving_editor->do_save (filename); X saving_editor = NULL; X if (closing_editor) // were we just closing this editor? X close_editor (False); X break; X X case (XmCR_CANCEL): X saving_editor = NULL; X break; X X default: X assert (False); // something is wrong.. X } X} SHAR_EOF $shar_touch -am 0512222696 'Red/Red/red_file.i' && chmod 0640 'Red/Red/red_file.i' || echo 'restore of Red/Red/red_file.i failed' shar_count="`wc -c < 'Red/Red/red_file.i'`" test 3616 -eq "$shar_count" || echo "Red/Red/red_file.i: original size 3616, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/requests ============== if test -f 'Red/Red/requests' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/requests (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/requests (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/requests' && XDONE: X----- Xo minimum thimb size -> not done because of scrolling problem Xo arrow down does not add lines Xo HOME and END keys: no X X============================= XMichael, what do you think about the following ideas: X X1. Editing multiple files with one Red window, using a menu of file names. X I suggest this because I often have (too) many Red windows open when X editing source files. X X2. The line number location of the cursor could be permanently displayed X somewhere rather than as a command. X X4. The scrolling jumps when using arrow keys to scroll. A smoother X line-by-line scrolling would be easier for students to understand. X XJust a few suggestions! X XLoki X-------------------------------------------- X XOne extra thing, is it all possible to make the cursor a bit more Xvisible? I sometimes have trouble finding it at a glance. X-- X Richard. X-------------------------------------------- XI agree with loki about the home and end key being used for begin and end of line. XIts more standard than the way red is now. Other than that red is a very easy Xeditor to use. X XShaddy Baddah X-------------------------------------------- XRed has provided a great editor for me, however I would like to add in Xmy own wishlist: X X1. Is it possible to set red up so that blocks of text may be Xhighlighted using shift-arrowkeys? This would be really good, as Red Xwould then conform to the same keystokes as most of the other editors I Xuse on various other platforms. X X2. When highlighting a block of text with the mouse, Red currently does Xnot scroll down (or up) so that at most 1 screen of text may be Xhighlighted & cut/copied etc. I know that this can be achieved using Xkeystrokes (although I have yet to work them out) but the rodent does Xprove more convenient on many occasions. X XThanks & congrads on a good program. X XStuart X-------------------------------------------- XAnother couple: X X3. Is it possible to do a block indent function so that pressing tab on Xa block indents the block by an extra tab stop on each line? (I have Xused this on other editors & it proves reaaly useful for programming) X X4. Can tab stops be set to a variable width ie 4 spaces not 8. This Xwould allow tabs to be used in programming without disappearing over the Xedge of the page too quickly. X XThe shift-enter function to auto-indent the next line is great! I like Xit! X XThanx X XStuart X Xjohnr: X X"windows" menu Xinsert file SHAR_EOF $shar_touch -am 0512222696 'Red/Red/requests' && chmod 0640 'Red/Red/requests' || echo 'restore of Red/Red/requests failed' shar_count="`wc -c < 'Red/Red/requests'`" test 2394 -eq "$shar_count" || echo "Red/Red/requests: original size 2394, current size $shar_count" rm -f _sharnew.tmp fi # ============= Red/Red/screen.cc ============== if test -f 'Red/Red/screen.cc' && test X"$1" != X"-c"; then echo 'x - skipping Red/Red/screen.cc (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting Red/Red/screen.cc (text)' sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/screen.cc' && X#include "screen.h" X#include "../Utility/utility.h" X#include "../Utility/debug.h" X X#define CURSOR_COLOUR "DeepPink4" X//#define SELECT_COLOUR "NavajoWhite" X//#define SELECT_COLOUR "MistyRose1" X#define SELECT_COLOUR "PaleVioletRed1" X X// ========================================================================= X// interface X// ========================================================================= X X// ------------------------------------------------------------------------- X// ------------------------------------------------------------------------- X XSCREEN::SCREEN (XFontStruct* screenfont, Boolean greytag) X : Spaces(" "), TAB_length(8), TAB(9), EOL(0) X{ X font = screenfont; X tag_grey = greytag; X first_init = True; X} X X// ------------------------------------------------------------------------- X// ------------------------------------------------------------------------- X Xvoid SCREEN::init (Widget draw_area, int tag_width) X{ X da = draw_area; X display = XtDisplay (draw_area); X window = XtWindow (draw_area); X X if (first_init) { X setup_gc (draw_area); X first_init = False; X } X left_offset = tag_width+2; // space for tag line X right_offset = fontwidth; // space needed for wrap mark X resize (); X cx = left_offset; column = 0; X cy = 0; line = 0; X X cursor_is_on = True; // True if user defined setting is "ON" X cursor_visible = False; // True if on at this moment X in_selection = False; X} X X// ------------------------------------------------------------------------- X// expose: called after an expose (of course) and after resize X// ------------------------------------------------------------------------- X Xvoid SCREEN::expose () X{ X // remove cursor from screen (can't know whether it is still drawn...) X XClearArea (display, window, cx-2, cy-2, 3, fontheight+4, False); X cursor_visible = False; X X // clear unused area UNDER last line X XClearArea (display, window, 0, lines*fontheight, 0, 0, False); X X if (tag_grey) { X XSetForeground (display, gcNorm, utility->backgroundColour); X XFillRectangle (display, window, gcNorm, 0, 0, left_offset-3, screenheight); X XSetForeground (display, gcNorm, utility->black); X } X XDrawLine (display, window, gcNorm, left_offset-3, 0, X left_offset-3, screenheight); X} X X// ------------------------------------------------------------------------- X// resize: X// ------------------------------------------------------------------------- X Xvoid SCREEN::resize () X{ X Arg al[10]; X int ac; X X // get size of draw area X ac=0; X XtSetArg (al[ac], XmNwidth, &screenwidth); ac++; X XtSetArg (al[ac], XmNheight, &screenheight); ac++; X XtGetValues (da, al, ac); X X lines = screenheight / fontheight; X columns = (screenwidth-left_offset-right_offset) / fontwidth; SHAR_EOF : || echo 'restore of Red/Red/screen.cc failed' fi echo 'End of archive part 6' echo 'File Red/Red/screen.cc is continued in part 7' echo 7 > _sharseq.tmp exit 0