~ubuntu-branches/ubuntu/raring/python-scipy/raring-proposed

« back to all changes in this revision

Viewing changes to Lib/sandbox/xplt/src/play/win/mfcterm.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-01-07 14:12:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070107141212-mm0ebkh5b37hcpzn
* Remove build dependency on python-numpy-dev.
* python-scipy: Depend on python-numpy instead of python-numpy-dev.
* Package builds on other archs than i386. Closes: #402783.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * mfcterm.cpp
 
3
 * richedit class for play MDI development environment
 
4
 *
 
5
 * Copyright (c) 1999.  See accompanying LEGAL file for details.
 
6
 */
 
7
 
 
8
#include "mfcapp.h"
 
9
#include "mfcterm.h"
 
10
#include "mfcres.h"
 
11
#include "playw.h"
 
12
 
 
13
#include <afxole.h>
 
14
 
 
15
#include <malloc.h>
 
16
 
 
17
#ifdef _DEBUG
 
18
#define new DEBUG_NEW
 
19
#undef THIS_FILE
 
20
static char THIS_FILE[] = __FILE__;
 
21
#endif
 
22
 
 
23
static HANDLE w_sending = 0;
 
24
static void mfc_sender(void *context);
 
25
static void mfc_stdout(char *output_line, long len);
 
26
static void mfc_stderr(char *output_line, long len);
 
27
static void mfc_bstdout(char *output_line);
 
28
static void mfc_bstderr(char *output_line);
 
29
static int mfc_deliver(const char *buf, long len);
 
30
 
 
31
static char *w_deprompt(char *text);
 
32
 
 
33
IMPLEMENT_DYNCREATE(mfc_edit_view, CRichEditView)
 
34
 
 
35
BEGIN_MESSAGE_MAP(mfc_edit_view, CRichEditView)
 
36
  ON_COMMAND(ID_GOTO_LINE, on_goto_line)
 
37
  ON_COMMAND(ID_GOTO_OUT, on_goto_out)
 
38
  ON_COMMAND(ID_SELECT_OUT, on_select_out)
 
39
  ON_COMMAND(ID_OPEN_LINE, on_open_line)
 
40
  ON_COMMAND(ID_CHOOSE_FILE, on_choose_file)
 
41
  ON_COMMAND(ID_EDIT_REDO, on_redo)
 
42
  ON_UPDATE_COMMAND_UI(ID_GOTO_OUT, on_update_term)
 
43
  ON_UPDATE_COMMAND_UI(ID_SELECT_OUT, on_update_term)
 
44
  ON_UPDATE_COMMAND_UI(ID_OPEN_LINE, on_update_term)
 
45
  ON_UPDATE_COMMAND_UI(ID_CHOOSE_FILE, on_update_term)
 
46
  ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, on_update_redo)
 
47
  ON_WM_CREATE()
 
48
 
 
49
  ON_COMMAND(ID_FILE_PRINT, CRichEditView::OnFilePrint)
 
50
  ON_COMMAND(ID_FILE_PRINT_DIRECT, CRichEditView::OnFilePrint)
 
51
  ON_COMMAND(ID_FILE_PRINT_PREVIEW, CRichEditView::OnFilePrintPreview)
 
52
END_MESSAGE_MAP()
 
53
 
 
54
mfc_edit_view::mfc_edit_view()
 
55
{
 
56
  m_nWordWrap = WrapNone;
 
57
  is_term = riched2 = 0;
 
58
}
 
59
 
 
60
mfc_edit_view::~mfc_edit_view()
 
61
{
 
62
}
 
63
 
 
64
BOOL
 
65
mfc_edit_view::PreCreateWindow(CREATESTRUCT& cs)
 
66
{
 
67
  BOOL result = CRichEditView::PreCreateWindow(cs);
 
68
 
 
69
#if (_RICHEDIT_VER < 0x200) && !defined(NO_RICHEDIT2)
 
70
// The following lines will turn on richedit 2.0 or 3.0 controls.
 
71
// However, the compatibility with the rest of the class is botched so that
 
72
//   many of the MFC functions only work with 1.0 semantics (_RICHEDIT_VER is
 
73
//   set in afxwin.h to force 1.0 in riched.h).
 
74
// I prefer not to risk this with the terminal and history windows, but
 
75
//   the lure of multilevel undo is irresistable for editor windows.
 
76
  static int re2_initialized = 0;
 
77
  if (result) {
 
78
    if (!re2_initialized) {
 
79
      if (!LoadLibraryA("riched20.dll"))  // riched32.dll is 1.0 version
 
80
        re2_initialized = 2;
 
81
      else
 
82
        re2_initialized = 1;
 
83
    }
 
84
    if (re2_initialized==1) {
 
85
      cs.lpszClass = RICHEDIT_CLASSA;  // RICHEDIT_CLASS set to 1.0 version
 
86
                                      // unless _RICHEDIT_VER >= 0x200
 
87
      riched2 = 1;
 
88
    }
 
89
  }
 
90
#endif
 
91
 
 
92
  return result;
 
93
}
 
94
 
 
95
void
 
96
mfc_edit_view::OnInitialUpdate()
 
97
{
 
98
  CRichEditView::OnInitialUpdate();
 
99
  // set the printing margins (720 twips = 1/2 inch).
 
100
  SetMargins(CRect(720, 720, 720, 720));
 
101
}
 
102
 
 
103
BOOL
 
104
mfc_edit_view::OnPreparePrinting(CPrintInfo* pInfo)
 
105
{
 
106
  // default preparation
 
107
  return DoPreparePrinting(pInfo);
 
108
}
 
109
 
 
110
void
 
111
mfc_edit_view::OnDestroy()
 
112
{
 
113
  CRichEditView::OnDestroy();
 
114
 
 
115
  // Deactivate the item on destruction; this is important
 
116
  // when a splitter view is being used.
 
117
  COleClientItem* item = GetDocument()->GetInPlaceActiveItem(this);
 
118
  if (item && item->GetActiveView()==this)
 
119
    item->Deactivate();
 
120
}
 
121
 
 
122
static CFont fixed_font;
 
123
static int font_init = 0;
 
124
 
 
125
int
 
126
mfc_edit_view::OnCreate(LPCREATESTRUCT lpcs)
 
127
{
 
128
  if (CCtrlView::OnCreate(lpcs) != 0)
 
129
    return -1;
 
130
  GetRichEditCtrl().LimitText(lMaxSize);
 
131
  GetRichEditCtrl().SetEventMask(ENM_SELCHANGE | ENM_CHANGE | ENM_SCROLL);
 
132
  VERIFY(GetRichEditCtrl().SetOLECallback(&m_xRichEditOleCallback));
 
133
  m_lpRichEditOle = GetRichEditCtrl().GetIRichEditOle();
 
134
  DragAcceptFiles(0);
 
135
  GetRichEditCtrl().SetOptions(ECOOP_OR, ECO_AUTOWORDSELECTION);
 
136
 
 
137
  if (!font_init) {
 
138
    HFONT f = (HFONT)GetStockObject(ANSI_FIXED_FONT);
 
139
        LOGFONT lf;
 
140
        if (::GetObject((HGDIOBJ)f, sizeof(LOGFONT), &lf)) {
 
141
      fixed_font.CreateFontIndirect(&lf);
 
142
    } else {
 
143
      return 1;
 
144
    }
 
145
    font_init = 1;
 
146
  }
 
147
  GetRichEditCtrl().SetFont(&fixed_font,0);
 
148
 
 
149
  WrapChanged();
 
150
  ASSERT(m_lpRichEditOle != NULL);
 
151
  return 0;
 
152
}
 
153
 
 
154
// without this, idiot will paste files and other objects into window
 
155
HRESULT
 
156
mfc_edit_view::QueryAcceptData(LPDATAOBJECT lpdataobj,
 
157
                               CLIPFORMAT* lpcfFormat, DWORD reco,
 
158
                               BOOL fReally, HGLOBAL hMetaPict)
 
159
{
 
160
  if (*lpcfFormat == CF_TEXT) return S_OK;
 
161
  COleDataObject dataobj;
 
162
  dataobj.Attach(lpdataobj, FALSE);
 
163
  if (*lpcfFormat==0 && dataobj.IsDataAvailable(CF_TEXT)) {
 
164
    *lpcfFormat = CF_TEXT;
 
165
    return S_OK;
 
166
  }
 
167
  return S_FALSE;
 
168
}
 
169
 
 
170
class mfc_goto : public CDialog
 
171
{
 
172
public:
 
173
  mfc_goto(mfc_edit_view *v);
 
174
  virtual void OnOK();
 
175
  mfc_edit_view *view;
 
176
  DECLARE_MESSAGE_MAP()
 
177
};
 
178
 
 
179
BEGIN_MESSAGE_MAP(mfc_goto, CDialog)
 
180
END_MESSAGE_MAP()
 
181
 
 
182
mfc_goto::mfc_goto(mfc_edit_view *v) : CDialog(IDD_GOTO_LINE)
 
183
{
 
184
  view = v;
 
185
}
 
186
 
 
187
void
 
188
mfc_goto::OnOK()
 
189
{
 
190
  CEdit *ce = (CEdit *)GetDlgItem(IDC_GOTO_LINE);
 
191
  char line[16];
 
192
  int n = ce->GetLine(0, line, 12);
 
193
  if (n>0) {
 
194
    line[n] = '\0';
 
195
    n = atoi(line)-1;
 
196
    if (n < 0) n = 0;
 
197
    n = view->GetRichEditCtrl().LineIndex(n);
 
198
    view->GetRichEditCtrl().SetSel(n,n);
 
199
  }
 
200
  CDialog::OnOK();
 
201
}
 
202
 
 
203
void
 
204
mfc_edit_view::on_goto_line()
 
205
{
 
206
  mfc_goto goto_dlg(this);
 
207
  goto_dlg.DoModal();
 
208
}
 
209
 
 
210
void
 
211
mfc_edit_view::on_redo()
 
212
{
 
213
  ASSERT(::IsWindow(m_hWnd));
 
214
  ::SendMessage(m_hWnd, EM_REDO, 0, 0);
 
215
  m_bSyncCharFormat = m_bSyncParaFormat = 1;
 
216
}
 
217
 
 
218
void
 
219
mfc_edit_view::on_update_term(CCmdUI *ui)
 
220
{
 
221
  ui->Enable(is_term);
 
222
}
 
223
 
 
224
void
 
225
mfc_edit_view::on_update_redo(CCmdUI *ui)
 
226
{
 
227
  if (riched2) {
 
228
    ASSERT(::IsWindow(m_hWnd));
 
229
    ui->Enable((BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0));
 
230
  } else {
 
231
    ui->Enable(0);
 
232
  }
 
233
}
 
234
 
 
235
/*------------------------------------------------------------------------*/
 
236
 
 
237
IMPLEMENT_DYNCREATE(mfc_edit_child, CMDIChildWnd)
 
238
 
 
239
BEGIN_MESSAGE_MAP(mfc_edit_child, CMDIChildWnd)
 
240
  ON_WM_CLOSE()
 
241
END_MESSAGE_MAP()
 
242
 
 
243
mfc_edit_child::mfc_edit_child()
 
244
{
 
245
}
 
246
 
 
247
mfc_edit_child::~mfc_edit_child()
 
248
{
 
249
}
 
250
 
 
251
void
 
252
mfc_edit_child::OnClose() 
 
253
{
 
254
  if (this == term_view->GetParent())
 
255
    AfxGetApp()->m_pMainWnd->SendMessage(WM_COMMAND, ID_VIEW_TERM, 0);
 
256
  else if (this == hist_view->GetParent())
 
257
    AfxGetApp()->m_pMainWnd->SendMessage(WM_COMMAND, ID_VIEW_HIST, 0);
 
258
  else
 
259
    CMDIChildWnd::OnClose();
 
260
}
 
261
 
 
262
/*------------------------------------------------------------------------*/
 
263
 
 
264
IMPLEMENT_DYNCREATE(mfc_edit_doc, CRichEditDoc)
 
265
 
 
266
BEGIN_MESSAGE_MAP(mfc_edit_doc, CRichEditDoc)
 
267
  //{{AFX_MSG_MAP(mfc_edit_doc)
 
268
  ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
 
269
  //}}AFX_MSG_MAP
 
270
  // Enable default OLE container implementation
 
271
  ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_LINKS, CRichEditDoc::OnUpdateEditLinksMenu)
 
272
  ON_COMMAND(ID_OLE_EDIT_LINKS, CRichEditDoc::OnEditLinks)
 
273
  ON_UPDATE_COMMAND_UI_RANGE(ID_OLE_VERB_FIRST, ID_OLE_VERB_LAST, CRichEditDoc::OnUpdateObjectVerbMenu)
 
274
END_MESSAGE_MAP()
 
275
 
 
276
mfc_edit_doc::mfc_edit_doc()
 
277
{
 
278
}
 
279
 
 
280
mfc_edit_doc::mfc_edit_doc(CMultiDocTemplate *mdt, int hist)
 
281
{
 
282
  mdt->AddDocument(this);
 
283
  m_pDocTemplate = mdt;
 
284
  mfc_edit_child *frame = new mfc_edit_child;
 
285
  CCreateContext context;
 
286
  context.m_pCurrentFrame = 0;
 
287
  context.m_pCurrentDoc = this;
 
288
  context.m_pNewViewClass = RUNTIME_CLASS(mfc_term_view);
 
289
  context.m_pNewDocTemplate = mdt;
 
290
  frame->LoadFrame(IDR_EDITFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,
 
291
                   0, &context);
 
292
  SetTitle(hist? "*history*" : "*terminal*");
 
293
  OnNewDocument();
 
294
  if (!hist)
 
295
    ((mfc_term_view *)GetView())->is_term = 1;
 
296
}
 
297
 
 
298
mfc_edit_doc::~mfc_edit_doc()
 
299
{
 
300
}
 
301
 
 
302
CRichEditCntrItem*
 
303
mfc_edit_doc::CreateClientItem(REOBJECT* preo) const
 
304
{
 
305
  return 0;
 
306
}
 
307
 
 
308
void
 
309
mfc_edit_doc::Serialize(CArchive& ar)
 
310
{
 
311
  if (ar.IsStoring()) {
 
312
    // TODO: add storing code here
 
313
  } else {
 
314
    // TODO: add loading code here
 
315
  }
 
316
 
 
317
  // Calling the base class CRichEditDoc enables serialization
 
318
  //  of the container document's COleClientItem objects.
 
319
  m_bRTF = 0;
 
320
  CRichEditDoc::Serialize(ar);
 
321
}
 
322
 
 
323
BOOL
 
324
mfc_edit_doc::OnNewDocument()
 
325
{
 
326
  if (!CRichEditDoc::OnNewDocument())
 
327
    return FALSE;
 
328
 
 
329
  // TODO: add reinitialization code here
 
330
  // (SDI documents will reuse this document)
 
331
 
 
332
  return TRUE;
 
333
}
 
334
 
 
335
BOOL
 
336
mfc_edit_doc::OnOpenDocument(LPCTSTR lpszPathName) 
 
337
{
 
338
  if (!CRichEditDoc::OnOpenDocument(lpszPathName))
 
339
    return FALSE;
 
340
 
 
341
  // TODO: Add your specialized creation code here
 
342
 
 
343
  return TRUE;
 
344
}
 
345
 
 
346
BOOL
 
347
mfc_edit_doc::SaveModified() 
 
348
{
 
349
  mfc_edit_view *view = (mfc_edit_view *)GetView();
 
350
  if (view==term_view || view==hist_view)
 
351
    return 1;
 
352
  else
 
353
    return CRichEditDoc::SaveModified();
 
354
}
 
355
 
 
356
void
 
357
mfc_edit_doc::OnFileClose() 
 
358
{
 
359
  mfc_edit_view *view = (mfc_edit_view *)GetView();
 
360
  if (view == term_view)
 
361
    AfxGetApp()->m_pMainWnd->SendMessage(WM_COMMAND, ID_VIEW_TERM, 0);
 
362
  else if (view == hist_view)
 
363
    AfxGetApp()->m_pMainWnd->SendMessage(WM_COMMAND, ID_VIEW_HIST, 0);
 
364
  else
 
365
    COleServerDoc::OnCloseDocument();
 
366
}
 
367
 
 
368
/*------------------------------------------------------------------------*/
 
369
 
 
370
IMPLEMENT_DYNCREATE(mfc_term_view, mfc_edit_view)
 
371
 
 
372
BEGIN_MESSAGE_MAP(mfc_term_view, mfc_edit_view)
 
373
  ON_COMMAND(ID_EDIT_UNDO, on_undo)
 
374
END_MESSAGE_MAP()
 
375
 
 
376
mfc_term_view::mfc_term_view()
 
377
{
 
378
  mark = smin = smax = len = 0;
 
379
  is_visible = recalling = recursing = 0;
 
380
}
 
381
 
 
382
mfc_term_view::~mfc_term_view()
 
383
{
 
384
}
 
385
 
 
386
BOOL
 
387
mfc_term_view::PreCreateWindow(CREATESTRUCT& cs)
 
388
{
 
389
  return CRichEditView::PreCreateWindow(cs);
 
390
}
 
391
 
 
392
void
 
393
mfc_term_view::OnInitialUpdate()
 
394
{
 
395
  mfc_edit_view::OnInitialUpdate();
 
396
}
 
397
 
 
398
LRESULT
 
399
mfc_term_view::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
 
400
{
 
401
  LRESULT result = 0;
 
402
  int key_unshifted = 0;
 
403
  long len0 = 0;
 
404
  int top = !recursing;
 
405
 
 
406
  if (top) {
 
407
    if (message==WM_DESTROY) top = 0;
 
408
    recursing = 1;
 
409
  }
 
410
 
 
411
  switch (message) {
 
412
  case WM_KEYDOWN:
 
413
  case WM_CHAR:
 
414
    key_unshifted = (GetKeyState(VK_SHIFT)>=0 && GetKeyState(VK_CONTROL)>=0 &&
 
415
                    GetKeyState(VK_MENU)>=0);
 
416
    if (key_unshifted) {
 
417
      if (wParam == '\r') {
 
418
        if (message == WM_KEYDOWN) {
 
419
          if (this == term_view) send_or_copy();
 
420
          else recall_line();
 
421
        }
 
422
        if (top) recursing = 0;
 
423
        return 0;
 
424
      } else if (this==term_view && message==WM_KEYDOWN) {
 
425
        if ((wParam==VK_UP || wParam==VK_DOWN) && at_eob()) {
 
426
          if (wParam == VK_UP)  recall_prev();
 
427
          else recall_next();
 
428
          recalling = 1;
 
429
          if (top) recursing = 0;
 
430
          return 0;
 
431
        }
 
432
      }
 
433
    }
 
434
    /* drop through */
 
435
  case WM_CUT:
 
436
  case WM_PASTE:
 
437
  case EM_REPLACESEL:
 
438
    get_state();
 
439
    result = CRichEditView::WindowProc(message, wParam, lParam);
 
440
    if (smin<mark ||
 
441
        (message==WM_KEYDOWN && wParam=='\b' && smin==smax && smin==mark)) {
 
442
      if (smax > mark) mark = smax;
 
443
      mark += eob() - len;
 
444
    }
 
445
    if (this==term_view && message==WM_KEYDOWN && wParam==VK_HOME)
 
446
      home_mark();
 
447
    recalling = 0;
 
448
    break;
 
449
 
 
450
  default:
 
451
    if (top && recalling) get_state();
 
452
    result = CRichEditView::WindowProc(message, wParam, lParam);
 
453
    if (top && recalling) {
 
454
      long smin0=smin, smax0=smax, len0=len;
 
455
      get_state();
 
456
      recalling = (smin0==smin && smax0==smax && len0==len);
 
457
    }
 
458
  }
 
459
 
 
460
  if (top) recursing = 0;
 
461
  return result;
 
462
}
 
463
 
 
464
void
 
465
mfc_term_view::on_undo()
 
466
{
 
467
  /* note: WM_UNDO never sent or never reaches WindowProc
 
468
   * -- neither does ID_EDIT_UNDO WM_COMMAND message?? */
 
469
  long len0 = eob();
 
470
  CRichEditView::OnEditUndo();
 
471
  get_state();
 
472
  if (smin < mark)
 
473
    mark += len - len0;
 
474
  recalling = 0;
 
475
}
 
476
 
 
477
void
 
478
mfc_term_view::get_state()
 
479
{
 
480
  len = eob();
 
481
  GetRichEditCtrl().GetSel(smin, smax);
 
482
}
 
483
 
 
484
long
 
485
mfc_term_view::bol(int offset)
 
486
{
 
487
  long line = GetRichEditCtrl().LineFromChar(-1);
 
488
  if (offset) {
 
489
    line += offset;
 
490
    if (line < 0)
 
491
      line = 0;
 
492
    else if (line >= GetRichEditCtrl().GetLineCount())
 
493
      line = GetRichEditCtrl().GetLineCount() - 1;
 
494
  }
 
495
  return GetRichEditCtrl().LineIndex(line);
 
496
}
 
497
 
 
498
long
 
499
mfc_term_view::eol(int offset)
 
500
{
 
501
  long i = bol(offset);
 
502
  return i + GetRichEditCtrl().LineLength(i);
 
503
}
 
504
 
 
505
long
 
506
mfc_term_view::eob(int beg)
 
507
{
 
508
  long i = GetRichEditCtrl().LineIndex(GetRichEditCtrl().GetLineCount() - 1);
 
509
  if (!beg) i += GetRichEditCtrl().LineLength(i);
 
510
  return i;
 
511
}
 
512
 
 
513
int
 
514
mfc_term_view::at_eob()
 
515
{
 
516
  long mn, mx;
 
517
  GetRichEditCtrl().GetSel(mn, mx);
 
518
  return (mn==mx && mx==eob());
 
519
}
 
520
 
 
521
CString
 
522
mfc_term_view::grab_line(int offset) const
 
523
{
 
524
  long line = GetRichEditCtrl().LineFromChar(-1);
 
525
  if (offset) {
 
526
    line += offset;
 
527
    if (line<0 || line>=GetRichEditCtrl().GetLineCount())
 
528
      return (const char *)0;
 
529
  }
 
530
  int len = GetRichEditCtrl().LineLength(GetRichEditCtrl().LineIndex(line));
 
531
  LPSTR s = (char*)_alloca((len + 2)*2);   // copied from MFC GetSelText
 
532
  GetRichEditCtrl().GetLine(line, s, len+2);
 
533
  s[len] = '\0';
 
534
  return s;
 
535
}
 
536
 
 
537
void
 
538
mfc_term_view::select_lines(int off1, int off2)
 
539
{
 
540
  GetRichEditCtrl().SetSel(bol(off1), bol(off2));
 
541
}
 
542
 
 
543
void
 
544
mfc_term_view::save_line(const char *txt)    // to end of hist_view
 
545
{
 
546
  long mn0, mx0;
 
547
  GetRichEditCtrl().GetSel(mn0, mx0);
 
548
  long i = eob(1);
 
549
  if (mx0 > i) mn0 = mx0 = i;
 
550
  GetRichEditCtrl().SetSel(i, eob(0));
 
551
  GetRichEditCtrl().ReplaceSel(txt);
 
552
  GetRichEditCtrl().SetSel(mn0, mx0);
 
553
}
 
554
 
 
555
void
 
556
mfc_term_view::set_command(const char *txt)  // at end of term_view
 
557
{
 
558
  GetRichEditCtrl().SetSel(mark, eob(0));
 
559
  GetRichEditCtrl().ReplaceSel(txt);
 
560
  long mn, mx;
 
561
  GetRichEditCtrl().GetSel(mn, mx);
 
562
  GetRichEditCtrl().SetSel(mx, mx);
 
563
}
 
564
 
 
565
void
 
566
mfc_term_view::add_output(const char *txt)   // at end of term_view
 
567
{
 
568
  if (::IsWindow(m_hWnd)) {
 
569
    long mn0, mx0, i, m = mark;
 
570
    GetRichEditCtrl().GetSel(mn0, mx0);
 
571
    GetRichEditCtrl().SetSel(mark, mark);
 
572
    GetRichEditCtrl().ReplaceSel(txt);
 
573
    GetRichEditCtrl().GetSel(i, mark);
 
574
    if (mx0>m || (mx0==m && mn0==mx0)) {
 
575
      if (mn0 < m) mn0 = mx0;
 
576
      mn0 += mark-m, mx0 += mark-m;
 
577
    }
 
578
    GetRichEditCtrl().SetSel(mn0, mx0);
 
579
  }
 
580
}
 
581
 
 
582
void
 
583
mfc_term_view::send_or_copy()  // bound to Enter in term_view
 
584
{
 
585
  long i, m;
 
586
  GetRichEditCtrl().GetSel(i, m);
 
587
  m = GetRichEditCtrl().LineIndex(GetRichEditCtrl().LineFromChar(mark));
 
588
  if (i >= m) {  // send new input as command line
 
589
    m = eob();
 
590
    //if (GetRichEditCtrl().LineLength(m)) {
 
591
      GetRichEditCtrl().SetSel(m, m);
 
592
      GetRichEditCtrl().ReplaceSel("\r\n");
 
593
      GetRichEditCtrl().GetSel(i, m);
 
594
    //}
 
595
    GetRichEditCtrl().SetSel(mark, m);
 
596
    CString txt = GetRichEditCtrl().GetSelText();
 
597
    if (mfc_deliver(txt, txt.GetLength())) {
 
598
      hist_view->save_line(txt);
 
599
      mark = m;
 
600
    }
 
601
    GetRichEditCtrl().SetSel(m, m);
 
602
 
 
603
  } else {       // copy current line as pending new command line
 
604
    CString txt = grab_line();
 
605
    set_command(w_deprompt((char *)(const char *)txt));
 
606
  }
 
607
}
 
608
 
 
609
void
 
610
mfc_term_view::recall_prev()   // bound to VK_UP in term_view
 
611
{
 
612
  long i;
 
613
  if (!recalling) {
 
614
    i = hist_view->eob(1);
 
615
    hist_view->GetRichEditCtrl().SetSel(i, i);
 
616
  } else {
 
617
    i = hist_view->bol();
 
618
  }
 
619
  long j = hist_view->bol(-1);
 
620
  if (j < i) {
 
621
    hist_view->GetRichEditCtrl().SetSel(j, j);
 
622
    CString txt = hist_view->grab_line();
 
623
    set_command(txt);
 
624
  } else {
 
625
    MessageBeep(MB_OK);
 
626
  }
 
627
}
 
628
 
 
629
void
 
630
mfc_term_view::recall_next()   // bound to VK_DOWN in term_view
 
631
{
 
632
  long i = hist_view->bol(1);
 
633
  if (i < hist_view->eob(1)) {
 
634
    hist_view->GetRichEditCtrl().SetSel(i, i);
 
635
    CString txt = hist_view->grab_line();
 
636
    set_command(txt);
 
637
  } else {
 
638
    MessageBeep(MB_OK);
 
639
  }
 
640
}
 
641
 
 
642
void
 
643
mfc_term_view::home_mark()     // after VK_HOME in term_view
 
644
{
 
645
  long i, m;
 
646
  GetRichEditCtrl().GetSel(i, m);
 
647
  if (i < mark) {  // adjust to mark
 
648
    if (GetRichEditCtrl().LineFromChar(mark) ==
 
649
        GetRichEditCtrl().LineFromChar(i))
 
650
      GetRichEditCtrl().SetSel(mark, mark);
 
651
  }
 
652
}
 
653
 
 
654
void
 
655
mfc_term_view::recall_line()   // bound to Enter in hist_view
 
656
{
 
657
  CString txt = grab_line();
 
658
  term_view->set_command(txt);
 
659
  long i = bol(0);     // get first char of current line
 
660
  if (i == bol(1)) {  // this line typed at end: send it
 
661
    term_view->send_or_copy();
 
662
    i = eob();
 
663
  } else if (term_view->is_visible) {
 
664
    CMDIFrameWnd *fw = (CMDIFrameWnd *)(the_boss.m_pMainWnd);
 
665
        fw->MDIActivate(term_view->GetParent());
 
666
  }
 
667
  GetRichEditCtrl().SetSel(i, i);
 
668
}
 
669
 
 
670
mfc_term_view *term_view = 0;
 
671
mfc_term_view *hist_view = 0;
 
672
 
 
673
/*------------------------------------------------------------------------*/
 
674
 
 
675
int
 
676
mfc_stdinit(void (**wout)(char*,long), void (**werr)(char*,long))
 
677
{ /* we are in worker thread here */
 
678
  int result = 1;
 
679
  *wout = *werr = 0;
 
680
  w_sending = CreateEvent(0, 1, 0, 0);
 
681
  if (w_sending) {
 
682
    the_boss.m_pMainWnd->SendMessage(ID_CALL_FUNC, (WPARAM)0,
 
683
                                     (LPARAM)&mfc_term_init);
 
684
    w_add_input(w_sending, mfc_sender, 0);
 
685
    *wout = mfc_stdout;
 
686
    *werr = mfc_stderr;
 
687
    result = 0;
 
688
  }
 
689
  return result;
 
690
}
 
691
 
 
692
/* ARGSUSED */
 
693
static void
 
694
mfc_sender(void *context)
 
695
{ /* we are in worker thread here */
 
696
  ResetEvent(w_sending);  /* set in boss thread to trigger this callback */
 
697
  w_deliver(w_sendbuf(-1));
 
698
}
 
699
 
 
700
static void
 
701
mfc_stdout(char *output_line, long len)
 
702
{ /* we are in worker thread here */
 
703
  if (the_boss.m_pMainWnd)
 
704
    the_boss.m_pMainWnd->SendMessage(ID_CALL_FUNC, (WPARAM)output_line,
 
705
                                     (LPARAM)&mfc_bstdout);
 
706
}
 
707
 
 
708
static void
 
709
mfc_stderr(char *output_line, long len)
 
710
{ /* we are in worker thread here */
 
711
  if (the_boss.m_pMainWnd)
 
712
    the_boss.m_pMainWnd->SendMessage(ID_CALL_FUNC, (WPARAM)output_line,
 
713
                                     (LPARAM)&mfc_bstderr);
 
714
}
 
715
 
 
716
static void
 
717
mfc_bstdout(char *output_line)
 
718
{ /* we are in boss thread here */
 
719
  term_view->add_output(output_line);
 
720
}
 
721
 
 
722
static void
 
723
mfc_bstderr(char *output_line)
 
724
{ /* we are in boss thread here */
 
725
  term_view->add_output(output_line);
 
726
}
 
727
 
 
728
static int
 
729
mfc_deliver(const char *buf, long len)
 
730
{ /* we are in boss thread here */
 
731
  int ready = (WaitForSingleObject(w_sending,0) == WAIT_TIMEOUT);
 
732
  if (ready && len>=0) {
 
733
    char *line = w_sendbuf(len);
 
734
    while (len--) *line++= *buf++;
 
735
    line[0] = '\0';
 
736
    SetEvent(w_sending);
 
737
  }
 
738
  return ready;
 
739
}
 
740
 
 
741
void
 
742
mfc_reset_stdin()
 
743
{ /* abandon any pending input if SIGINT received
 
744
   * -- without this, deadlock is possible
 
745
   * -- actually, should be called from wpoll when clearing queue */
 
746
  ResetEvent(w_sending);
 
747
}
 
748
 
 
749
/*------------------------------------------------------------------------*/
 
750
 
 
751
void
 
752
mfc_edit_view::on_choose_file()
 
753
{
 
754
  CFileDialog dlg(1);
 
755
  CString name;
 
756
  dlg.m_ofn.lpstrTitle = "Insert Filename";
 
757
  dlg.m_ofn.lpstrFile = name.GetBuffer(1025);
 
758
  if (dlg.DoModal() == IDOK)
 
759
    GetRichEditCtrl().ReplaceSel(name);
 
760
  name.ReleaseBuffer();
 
761
}
 
762
 
 
763
void
 
764
mfc_edit_view::on_goto_out()
 
765
{
 
766
  int len;
 
767
  char s[80];
 
768
  long line = GetRichEditCtrl().LineFromChar(-1);
 
769
  for (line-- ; line>0 ; line--) {
 
770
    len = GetRichEditCtrl().LineLength(GetRichEditCtrl().LineIndex(line));
 
771
    if (len>78) len = 78;
 
772
    GetRichEditCtrl().GetLine(line, s, len);
 
773
    s[len] = '\0';
 
774
    if (w_deprompt(s) != s) break;
 
775
  }
 
776
  line = GetRichEditCtrl().LineIndex(line+1);
 
777
  GetRichEditCtrl().SetSel(line, line);
 
778
}
 
779
 
 
780
void
 
781
mfc_edit_view::on_select_out()
 
782
{
 
783
  int len;
 
784
  char s[80];
 
785
  long line = GetRichEditCtrl().LineFromChar(-1);
 
786
  long linemx = GetRichEditCtrl().GetLineCount();
 
787
  long line0 = line;
 
788
  long i, j;
 
789
  for (line-- ; line>=0 ; line--) {
 
790
    len = GetRichEditCtrl().LineLength(GetRichEditCtrl().LineIndex(line));
 
791
    if (len>78) len = 78;
 
792
    GetRichEditCtrl().GetLine(line, s, len);
 
793
    s[len] = '\0';
 
794
    if (w_deprompt(s) != s) break;
 
795
  }
 
796
  i = GetRichEditCtrl().LineIndex(line+1);
 
797
  for (line=line0 ; line<linemx ; line++) {
 
798
    len = GetRichEditCtrl().LineLength(GetRichEditCtrl().LineIndex(line));
 
799
    if (len>78) len = 78;
 
800
    GetRichEditCtrl().GetLine(line, s, len);
 
801
    s[len] = '\0';
 
802
    if (w_deprompt(s) != s) break;
 
803
  }
 
804
  j = GetRichEditCtrl().LineIndex(line);
 
805
  GetRichEditCtrl().SetSel(i, j);
 
806
}
 
807
 
 
808
void
 
809
mfc_edit_view::on_open_line()
 
810
{
 
811
  int len, i, n, oline=0;
 
812
  char s[1076];
 
813
  long line = GetRichEditCtrl().LineFromChar(-1);
 
814
  for (n=0 ; n<10 ; n++,line--) {
 
815
    len = GetRichEditCtrl().LineLength(GetRichEditCtrl().LineIndex(line));
 
816
    if (len>1075) len = 1075;
 
817
    GetRichEditCtrl().GetLine(line, s, len);
 
818
    s[len] = '\0';
 
819
    for (i=4 ; i<len-8 ; i++) {
 
820
      if (s[i]==':' &&
 
821
          s[i-1]=='E' && s[i-2]=='N' && s[i-3]=='I' && s[i-4]=='L') {
 
822
        for (i++ ; i<len-7 ; i++) if (s[i]!=' ' && s[i]!='\t') break;
 
823
        while (s[i]>='0' && s[i]<='9') oline = 10*oline + (s[i++]-'0');
 
824
        for (i+=4 ; i<len-1 ; i++) {
 
825
          if (s[i]==':' &&
 
826
              s[i-1]=='E' && s[i-2]=='L' && s[i-3]=='I' && s[i-4]=='F') {
 
827
            for (i++ ; i<len ; i++) if (s[i]!=' ' && s[i]!='\t') break;
 
828
            if (i < len) {
 
829
              /* document name s line number oline */
 
830
              mfc_edit_doc *doc=
 
831
                (mfc_edit_doc *)the_boss.OpenDocumentFile(&s[i]);
 
832
              if (doc) {
 
833
                mfc_edit_view *view = (mfc_edit_view *)doc->GetView();
 
834
                long ll = view->GetRichEditCtrl().LineIndex(oline-1);
 
835
                view->GetRichEditCtrl().SetSel(ll, ll);
 
836
              } else {
 
837
                MessageBeep(MB_OK);
 
838
              }
 
839
              return;
 
840
            }
 
841
          }
 
842
        }
 
843
      }
 
844
    }
 
845
  }
 
846
  MessageBeep(MB_OK);
 
847
}
 
848
 
 
849
static char *
 
850
w_deprompt(char *text)
 
851
{
 
852
  char *t = text;
 
853
  /* remove regexp "^[a-zA-Z0-9_-]*> *" from text */
 
854
  while ((t[0]>='a' && t[0]<='z') || (t[0]>='A' && t[0]<='Z') ||
 
855
         (t[0]>='0' && t[0]<='9') || t[0]=='_' || t[0]=='-') t++;
 
856
  if (t[0]=='>') {
 
857
    t++;
 
858
    while (t[0]==' ' || t[0]=='\t') t++;
 
859
  } else {
 
860
    t = text;
 
861
  }
 
862
  return t;
 
863
}