Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

open-axiom repository from github

24005 views
1
/*
2
Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd.
3
All rights reserved.
4
Copyright (C) 2007-2010, Gabriel Dos Reis.
5
All rights reserved.
6
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are
9
met:
10
11
- Redistributions of source code must retain the above copyright
12
notice, this list of conditions and the following disclaimer.
13
14
- Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the following disclaimer in
16
the documentation and/or other materials provided with the
17
distribution.
18
19
- Neither the name of The Numerical Algorithms Group Ltd. nor the
20
names of its contributors may be used to endorse or promote products
21
derived from this software without specific prior written permission.
22
23
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
27
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
*/
35
36
/******************************************************************************
37
*
38
* dialog.c:
39
*
40
* Copyright The Numerical Algorithms Group Limited 1991, 1992, 1993.
41
*
42
****************************************************************************/
43
#include <X11/keysym.h>
44
45
#define _DIALOG_C
46
#include "openaxiom-c-macros.h"
47
48
#include "debug.h"
49
50
#include "sockio.h"
51
#include "hyper.h"
52
#include "keyin.h"
53
#include "display.h"
54
#include "group.h"
55
#include "event.h"
56
57
58
#define min(x,y) ( (x<y)?(x):(y))
59
60
61
62
static void back_over_char(InputItem * sym);
63
static void back_over_eoln(InputItem * sym);
64
static void clear_cursor(InputItem * sym);
65
static void clear_cursorline(InputItem * sym);
66
static void dec_line_numbers(LineStruct * line);
67
static void decrease_line_numbers(LineStruct * line , int am);
68
static void delete_char(InputItem * sym);
69
static void delete_eoln(InputItem * sym);
70
static int delete_one_char(InputItem * sym);
71
static void delete_rest_of_line(InputItem * sym);
72
static void draw_cursor(InputItem * sym);
73
static void enter_new_line(InputItem * sym);
74
static void inc_line_numbers(LineStruct * line);
75
static void insert_buffer(char * buffer , InputItem * sym);
76
static int move_back_one_char(InputItem * sym);
77
static void move_cursor_backward(InputItem * sym);
78
static void move_cursor_down(InputItem * sym);
79
static void move_cursor_end(InputItem * sym);
80
static void move_cursor_forward(InputItem * sym);
81
static void move_cursor_home(InputItem * sym);
82
static void move_cursor_up(InputItem * sym);
83
static char move_rest_back(LineStruct * line , int size);
84
static int move_sym_forward(LineStruct * line , int num , int size , InputItem * sym);
85
static char * mystrncpy(char * buff1 , char * buff2 , int n);
86
static void overwrite_buffer(char * buffer , InputItem * item);
87
static void redraw_win();
88
static void tough_enter(InputItem * sym);
89
90
static void
91
redraw_win()
92
{
93
XUnmapSubwindows(gXDisplay, gWindow->fMainWindow);
94
XUnmapSubwindows(gXDisplay, gWindow->fScrollWindow);
95
XFlush(gXDisplay);
96
show_page(gWindow->page);
97
}
98
99
static char *
100
mystrncpy(char *buff1, char *buff2, int n)
101
{
102
/*
103
* copies the characters from buff1 to buff2 starting at position buff2 +
104
* n and buff1 + n
105
*/
106
107
int i;
108
109
for (i = n - 1; i >= 0; i--)
110
*(buff1 + i) = *(buff2 + i);
111
return buff2;
112
}
113
114
static void
115
inc_line_numbers(LineStruct *line)
116
{
117
for (; line != NULL; line = line->next)
118
line->line_number++;
119
}
120
121
static void
122
dec_line_numbers(LineStruct *line)
123
{
124
for (; line != NULL; line = line->next)
125
line->line_number--;
126
return;
127
}
128
129
static void
130
decrease_line_numbers(LineStruct *line, int am)
131
{
132
for (; line != NULL; line = line->next)
133
line->line_number -= am;
134
}
135
136
static void
137
overwrite_buffer(char *buffer, InputItem *item)
138
{
139
LineStruct *newline;
140
LineStruct *addline = item->curr_line;
141
/*int bufflen = strlen(buffer);*/
142
int nl = 0;
143
int cursor_y;
144
int size = item->size;
145
146
/* add a single character */
147
148
cursor_y = (addline->line_number - 1) * line_height;
149
if (addline->buff_pntr == size) {
150
clear_cursor(item);
151
if (addline->len <= size) {
152
nl = 1;
153
addline->buffer[size] = '_';
154
addline->buffer[size + 1] = 0;
155
addline->len = size + 1;
156
newline = (LineStruct *) alloc_inputline(size + 2);
157
newline->line_number = addline->line_number + 1;
158
inc_line_numbers(addline->next);
159
newline->next = addline->next;
160
newline->prev = addline;
161
if (addline->next)
162
addline->next->prev = newline;
163
addline->next = newline;
164
item->num_lines++;
165
cursor_y += line_height;
166
item->curr_line = addline = newline;
167
}
168
else {
169
item->curr_line = addline = addline->next;
170
}
171
addline->len = 1;
172
addline->buff_pntr = 1;
173
addline->buffer[0] = buffer[0];
174
}
175
else {
176
addline->buffer[addline->buff_pntr] = buffer[0];
177
clear_cursor(item);
178
if (++addline->buff_pntr > addline->len)
179
addline->len++;
180
}
181
182
/* now set up the current line */
183
if (item->curr_line->buff_pntr >= item->size &&
184
item->curr_line->next != NULL && !item->curr_line->next->len) {
185
/* I should actually be on the next line */
186
item->curr_line->buffer[item->size] = '_';
187
item->curr_line->len = item->size + 1;
188
XDrawString(gXDisplay, item->win, gWindow->fInputGC, start_x,
189
cursor_y + start_y,
190
addline->buffer,
191
addline->len);
192
item->curr_line = item->curr_line->next;
193
item->curr_line->buff_pntr = 0;
194
item->curr_line->changed = 1;
195
}
196
197
if (!nl) {
198
XDrawString(gXDisplay, item->win, gWindow->fInputGC, start_x,
199
cursor_y + start_y,
200
addline->buffer,
201
addline->len);
202
draw_cursor(item);
203
}
204
else
205
redraw_win();
206
}
207
208
/*
209
* This routine takes the current line and moves it num forward. The
210
* only way I have to move any other lines forward is if this line has length
211
* > size
212
*/
213
214
static int
215
move_sym_forward(LineStruct *line, int num, int size, InputItem *sym)
216
{
217
LineStruct *newline;
218
int diff;
219
int nl = 0;
220
221
if (line->len > size) {
222
nl = move_sym_forward(line->next, num, size, sym);
223
strncpy(line->next->buffer,
224
&line->buffer[sym->size - num], line->len);
225
strncpy(&line->buffer[num],
226
line->buffer, num);
227
line->changed = 1;
228
return nl;
229
}
230
else {
231
if (line->len + num > size) {
232
diff = line->len + num - size;
233
newline = alloc_inputline(size);
234
newline->len = diff;
235
newline->line_number = line->line_number++;
236
inc_line_numbers(line->next);
237
sym->num_lines++;
238
newline->next = line->next;
239
newline->prev = line;
240
if (line->next)
241
line->next->prev = newline;
242
line->next = newline;
243
strncpy(newline->buffer, &line->buffer[size - diff], diff);
244
strncpy(&line->buffer[num], line->buffer, num);
245
line->buffer[size] = '_';
246
line->buffer[size + 1] = 0;
247
line->len = size + 1;
248
return 1;
249
}
250
else {
251
strncpy(&line->buffer[num], line->buffer, line->len);
252
line->len += num;
253
line->changed = 1;
254
return 0;
255
}
256
}
257
}
258
259
static void
260
clear_cursorline(InputItem *sym)
261
{
262
XCharStruct extents;
263
int dir, asc, des;
264
int cursor_y;
265
266
XTextExtents(gInputFont, sym->curr_line->buffer,
267
sym->curr_line->buff_pntr,
268
&dir, &asc, &des, &extents);
269
cursor_y = (sym->curr_line->line_number - 1) * line_height;
270
sym->cursor_x = start_x + extents.width;
271
XClearArea(gXDisplay, sym->win, sym->cursor_x, cursor_y,
272
gWindow->width, line_height, False);
273
XDrawString(gXDisplay, sym->win, gWindow->fInputGC, start_x, cursor_y + start_y,
274
sym->curr_line->buffer,
275
sym->curr_line->len);
276
}
277
278
static void
279
insert_buffer(char *buffer, InputItem *sym)
280
{
281
/*int num = strlen(buffer);*/
282
LineStruct *line = sym->curr_line;
283
LineStruct *newline;
284
int nl = 0;
285
int size = sym->size;
286
287
if (line->len < size) {
288
/* they will all fit where I am so just copy them forward */
289
line->len++;
290
mystrncpy(&(line->buffer[line->buff_pntr + 1]),
291
&(line->buffer[line->buff_pntr]),
292
line->len - line->buff_pntr + 1);
293
line->buffer[line->buff_pntr] = buffer[0];
294
clear_cursorline(sym);
295
line->buff_pntr++;
296
draw_cursor(sym);
297
return;
298
}
299
300
if (line->len > sym->size) {
301
nl = move_sym_forward(line->next, 1, size, sym);
302
if (line->buff_pntr > size) {
303
line->changed = 1;
304
line = line->next;
305
line->buffer[0] = buffer[0];
306
line->len++;
307
line->buff_pntr = 1;
308
line->changed = 1;
309
}
310
else {
311
line->next->buffer[0] = line->buffer[size - 1];
312
line->changed = 1;
313
strncpy(&line->buffer[line->buff_pntr + 1],
314
&line->buffer[line->buff_pntr], size - line->buff_pntr - 1);
315
line->buffer[line->buff_pntr++] = buffer[0];
316
line->changed = 1;
317
if (line->buff_pntr >= size) {
318
sym->curr_line = line->next;
319
sym->curr_line->buff_pntr = 0;
320
}
321
}
322
}
323
else {
324
nl = 1;
325
newline = alloc_inputline(size);
326
newline->line_number = line->line_number + 1;
327
inc_line_numbers(line->next);
328
sym->num_lines++;
329
newline->next = line->next;
330
newline->prev = line;
331
if (line->next)
332
line->next->prev = newline;
333
line->next = newline;
334
335
/*
336
* was line->buff_pntr++;
337
*/
338
if (line->buff_pntr >= size) {
339
/* we are the leaders of the line */
340
newline->buff_pntr = 1;
341
newline->buffer[0] = buffer[0];
342
newline->len = 1;
343
sym->curr_line = newline;
344
}
345
else {
346
/* we are not the leaders */
347
newline->buffer[0] = line->buffer[size - 1];
348
newline->len = 1;
349
strncpy(&line->buffer[line->buff_pntr + 1],
350
&line->buffer[line->buff_pntr], size - line->buff_pntr);
351
if (line->buff_pntr < size - 1) {
352
line->buffer[line->buff_pntr++] = buffer[0];
353
}
354
else {
355
line->buffer[line->buff_pntr] = buffer[0];
356
newline->buff_pntr = 0;
357
sym->curr_line = newline;
358
}
359
360
}
361
line->buffer[size] = '_';
362
line->buffer[size + 1] = 0;
363
line->len = size + 1;
364
}
365
if (nl)
366
redraw_win();
367
else
368
update_inputsymbol(sym);
369
370
}
371
372
void
373
add_buffer_to_sym(char *buffer,InputItem *sym)
374
{
375
if (gInInsertMode)
376
insert_buffer(buffer, sym);
377
else
378
overwrite_buffer(buffer, sym);
379
}
380
381
void
382
draw_inputsymbol(InputItem *sym)
383
{
384
int y_spot = start_y;
385
LineStruct *cline;
386
XCharStruct extents;
387
int dir, asc, des;
388
389
390
#if 0
391
int cursor_y;
392
cursor_y = (sym->curr_line->line_number - 1) * line_height;
393
#endif
394
395
XClearWindow(gXDisplay, sym->win);
396
397
XTextExtents(gInputFont, sym->curr_line->buffer,
398
sym->curr_line->buff_pntr,
399
&dir, &asc, &des, &extents);
400
sym->cursor_x = start_x + extents.width;
401
402
/*
403
* While the list of input strings is not NULL, I should just keep
404
* drawing them
405
*/
406
for (cline = sym->lines; cline != NULL;
407
cline = cline->next, y_spot += line_height) {
408
/* Now I should draw the initial string ** */
409
cline->changed = 0;
410
XDrawString(gXDisplay, sym->win, gWindow->fInputGC, start_x, y_spot,
411
cline->buffer,
412
cline->len);
413
414
}
415
if (gWindow->page->current_item == sym)
416
draw_cursor(sym);
417
}
418
419
void
420
update_inputsymbol(InputItem *sym)
421
{
422
int y_spot = start_y;
423
LineStruct *cline;
424
XCharStruct extents;
425
int dir, asc, des;
426
/*int cleared = 0;*/
427
int clear_y;
428
int clear_width;
429
int clear_height;
430
431
#if 0
432
int cursor_y;
433
cursor_y = (sym->curr_line->line_number - 1) * line_height;
434
#endif
435
436
clear_width = (sym->size + 1) * gInputFont->max_bounds.width + 10;
437
clear_height = line_height;
438
clear_y = 0;
439
440
441
XTextExtents(gInputFont, sym->curr_line->buffer,
442
sym->curr_line->buff_pntr,
443
&dir, &asc, &des, &extents);
444
sym->cursor_x = start_x + extents.width;
445
446
/*
447
* While the list of input strings is not NULL, I should just keep
448
* drawing them
449
*/
450
for (cline = sym->lines; cline != NULL;
451
cline = cline->next, y_spot += line_height, clear_y += line_height)
452
/* Now I should draw the initial string ** */
453
if (cline->changed) {
454
cline->changed = 0;
455
XClearArea(gXDisplay, sym->win, 0, clear_y,
456
clear_width, clear_height, False);
457
XDrawString(gXDisplay, sym->win, gWindow->fInputGC, start_x, y_spot,
458
cline->buffer,
459
cline->len);
460
}
461
draw_cursor(sym);
462
}
463
464
465
static void
466
draw_cursor(InputItem *sym)
467
{
468
int cursor_y;
469
XCharStruct extents;
470
int dir, asc, des;
471
472
473
cursor_y = (sym->curr_line->line_number - 1) * line_height;
474
XTextExtents(gInputFont, sym->curr_line->buffer,
475
sym->curr_line->buff_pntr,
476
&dir, &asc, &des, &extents);
477
sym->cursor_x = start_x + extents.width;
478
/* now draw the cursor */
479
if (gInInsertMode) {
480
XFillRectangle(gXDisplay, sym->win, gWindow->fInputGC,
481
sym->cursor_x,
482
out_cursor_y + cursor_y,
483
out_cursor_width,
484
out_cursor_height);
485
486
/* Now draw the character currently under the cursor */
487
488
XDrawString(gXDisplay, sym->win, gWindow->fCursorGC,
489
sym->cursor_x, cursor_y + start_y,
490
&sym->curr_line->buffer[sym->curr_line->buff_pntr],
491
1);
492
}
493
else
494
XFillRectangle(gXDisplay, sym->win, gWindow->fInputGC,
495
sym->cursor_x,
496
in_cursor_y + cursor_y,
497
in_cursor_width,
498
in_cursor_height);
499
}
500
501
static void
502
move_cursor_home(InputItem *sym)
503
{
504
LineStruct *trace = sym->curr_line;
505
506
/* now move the cursor to the beginning of the current line */
507
clear_cursor(sym);
508
for (; trace && trace->prev && trace->prev->len > sym->size;)
509
trace = trace->prev;
510
sym->curr_line = trace;
511
trace->buff_pntr = 0;
512
draw_cursor(sym);
513
}
514
515
static void
516
move_cursor_end(InputItem *sym)
517
{
518
LineStruct *trace = sym->curr_line;
519
520
/* now move the cursor to the beginning of the current line */
521
clear_cursor(sym);
522
for (; trace && trace->next && trace->len > sym->size;)
523
trace = trace->next;
524
sym->curr_line = trace;
525
trace->buff_pntr = trace->len;
526
draw_cursor(sym);
527
}
528
529
static void
530
move_cursor_forward(InputItem *sym)
531
{
532
if (sym->curr_line->buff_pntr == sym->curr_line->len &&
533
!sym->curr_line->next) {
534
BeepAtTheUser();
535
return;
536
}
537
538
539
if (sym->curr_line->buff_pntr == sym->curr_line->len ||
540
sym->curr_line->buff_pntr == sym->size - 1)
541
{
542
543
/* I have to move down to a new line */
544
545
if (sym->curr_line->next == NULL) {
546
/* now where to move */
547
BeepAtTheUser();
548
return;
549
}
550
551
/* move down line */
552
553
clear_cursor(sym);
554
sym->curr_line = sym->curr_line->next;
555
sym->curr_line->buff_pntr = 0;
556
}
557
else {
558
clear_cursor(sym);
559
sym->curr_line->buff_pntr++;
560
}
561
562
draw_cursor(sym);
563
}
564
565
static void
566
move_cursor_down(InputItem *sym)
567
{
568
int bp = sym->curr_line->buff_pntr;
569
/*int size = sym->size;*/
570
LineStruct *trace;
571
572
/* get to the end of the current line */
573
574
for (trace = sym->curr_line; trace->len > sym->size; trace = trace->next)
575
;
576
577
if (!trace->next)
578
BeepAtTheUser();
579
else {
580
clear_cursor(sym);
581
sym->curr_line = trace->next;
582
if (bp > sym->curr_line->len)
583
sym->curr_line->buff_pntr = sym->curr_line->len;
584
else
585
sym->curr_line->buff_pntr = bp;
586
draw_cursor(sym);
587
}
588
}
589
590
static void
591
move_cursor_up(InputItem *sym)
592
{
593
int bp = sym->curr_line->buff_pntr;
594
/*int size = sym->size;*/
595
LineStruct *trace;
596
597
/* get to the end of the current line */
598
for (trace = sym->curr_line;
599
trace->prev && trace->prev->len > sym->size;
600
trace = trace->prev)
601
;
602
603
if (!trace->prev)
604
BeepAtTheUser();
605
else {
606
clear_cursor(sym);
607
sym->curr_line = trace->prev;
608
if (bp > sym->curr_line->len)
609
sym->curr_line->buff_pntr = sym->curr_line->len;
610
else
611
sym->curr_line->buff_pntr = bp;
612
draw_cursor(sym);
613
}
614
}
615
616
static void
617
clear_cursor(InputItem *sym)
618
{
619
XCharStruct extents;
620
int dir, asc, des;
621
int cursor_y;
622
623
XTextExtents(gInputFont, sym->curr_line->buffer,
624
sym->curr_line->buff_pntr,
625
&dir, &asc, &des, &extents);
626
cursor_y = (sym->curr_line->line_number - 1) * line_height;
627
sym->cursor_x = start_x + extents.width;
628
XClearArea(gXDisplay, sym->win, sym->cursor_x, cursor_y,
629
in_cursor_width, line_height, False);
630
631
XDrawString(gXDisplay, sym->win, gWindow->fInputGC,
632
start_x, cursor_y + start_y,
633
sym->curr_line->buffer,
634
sym->curr_line->len);
635
}
636
637
static void
638
move_cursor_backward(InputItem *sym)
639
{
640
if (sym->curr_line->buff_pntr == 0) {
641
if (sym->curr_line->prev == NULL) {
642
/* now where to move */
643
BeepAtTheUser();
644
return;
645
}
646
else {
647
clear_cursor(sym);
648
/* move up to the previous line */
649
sym->curr_line = sym->curr_line->prev;
650
if (sym->curr_line->len > sym->size)
651
sym->curr_line->buff_pntr = sym->size - 1;
652
else
653
sym->curr_line->buff_pntr = sym->curr_line->len;
654
}
655
}
656
else { /* just slide back a char. on the current
657
* line */
658
clear_cursor(sym);
659
sym->curr_line->buff_pntr--;
660
}
661
draw_cursor(sym);
662
}
663
664
static char
665
move_rest_back(LineStruct *line, int size)
666
{
667
char c = '\000';
668
669
if (line != NULL && line->len != 0)
670
c = line->buffer[0];
671
else
672
return c;
673
674
while (line->next != NULL && line->len > size) {
675
strncpy(line->buffer, &(line->buffer[1]), size - 1);
676
line->buffer[size - 1] = line->next->buffer[0];
677
line->changed = 1;
678
line = line->next;
679
}
680
681
/*
682
* once I get here I should be one the last line, so I can just copy all
683
* the characters back one and then return from whence I came ***
684
*/
685
if (line->len > 0) {
686
line->changed = 1;
687
if (line->len > 1)
688
strncpy(line->buffer, &(line->buffer[1]), line->len - 1);
689
line->buffer[--line->len] = 0;
690
if (line->len == 0) {
691
/* I have to fix the previous line */
692
line->prev->len = size;
693
line->prev->buffer[size] = 0;
694
}
695
}
696
return c;
697
}
698
699
static void
700
delete_rest_of_line(InputItem *sym)
701
{
702
LineStruct *curr_line = sym->curr_line;
703
LineStruct *line=NULL;
704
LineStruct *trash;
705
LineStruct *trace;
706
int num_changed = 0, i;
707
708
if (curr_line->len > sym->size) {
709
for (line = curr_line->next, num_changed = 0;
710
line != NULL && line->len > 0 && line->len > sym->size;
711
line = line->next, num_changed++) {
712
line->len = 0;
713
line->buffer[0] = 0;
714
line->changed = 1;
715
}
716
num_changed++;
717
}
718
719
if (num_changed == 0 && curr_line->buff_pntr == curr_line->len) {
720
if (curr_line->len == 0 && curr_line->next) {
721
curr_line->next->prev = curr_line->prev;
722
if (curr_line->prev)
723
curr_line->prev->next = curr_line->next;
724
else
725
sym->lines = curr_line->next;
726
dec_line_numbers(curr_line->next);
727
sym->num_lines--;
728
sym->curr_line = curr_line->next;
729
sym->curr_line->buff_pntr = 0;
730
free(curr_line->buffer);
731
free(curr_line);
732
redraw_win();
733
}
734
else
735
BeepAtTheUser();
736
return;
737
}
738
739
curr_line->len = curr_line->buff_pntr;
740
741
/* curr_line->buffer[curr_line->len] = NULL; */
742
743
for (i = curr_line->len; i <= sym->size + 2; i++)
744
curr_line->buffer[i] = 0;
745
746
curr_line->changed = 1;
747
748
if (num_changed) {
749
/* I should get rid of all these lines */
750
trace = curr_line->next;
751
curr_line->next = line->next;
752
if (line->next)
753
line->next->prev = curr_line;
754
for (; trace && trace != line->next;) {
755
trash = trace;
756
trace = trace->next;
757
free(trash->buffer);
758
free(trash);
759
}
760
decrease_line_numbers(curr_line->next, num_changed);
761
sym->num_lines -= num_changed;
762
redraw_win();
763
}
764
else
765
update_inputsymbol(sym);
766
}
767
768
static void
769
back_over_eoln(InputItem *sym)
770
{
771
/*
772
* This routine is very similar to a tough enter except it starts
773
* combining lines with sym->curr_line->pre
774
*/
775
776
char buff[1024];
777
LineStruct *trace;
778
LineStruct *last = NULL;
779
char *tr = buff;
780
int bp;
781
int size = sym->size;
782
783
/* copy all the stuff into the buffer */
784
for (trace = sym->curr_line;
785
trace->len > sym->size; trace = trace->next)
786
for (bp = 0; bp < size; bp++)
787
*tr++ = trace->buffer[bp];
788
789
/* copy the last line */
790
for (bp = 0; bp < trace->len; bp++)
791
*tr++ = trace->buffer[bp];
792
trace->len = 0;
793
*tr = 0;
794
795
/* Now that I have the buffer, let's put it back where it belongs. */
796
last = trace;
797
for (trace = sym->curr_line; trace != last; trace = trace->next);
798
trace = sym->curr_line = sym->curr_line->prev;
799
trace->buff_pntr = trace->len;
800
trace->changed = 1;
801
for (bp = trace->len, tr = buff; bp < size && *tr; bp++)
802
trace->buffer[bp] = *tr++;
803
804
if (!*tr) {
805
trace->len = bp;
806
}
807
else {
808
trace->len = size + 1;
809
trace->buffer[size] = '_';
810
trace->buffer[size + 1] = 0;
811
for (trace = trace->next; *tr;) {
812
for (bp = 0; bp < size && *tr; bp++)
813
trace->buffer[bp] = *tr++;
814
if (*tr) {
815
trace->len = size + 1;
816
trace->changed = 1;
817
trace->buffer[size + 1] = 0;
818
trace->buffer[size] = '_';
819
trace = trace->next;
820
}
821
else {
822
trace->len = bp;
823
trace->buffer[bp] = 0;
824
}
825
}
826
}
827
/* Now once I am here, let me see if I can bag a line */
828
if (last->len == 0) {
829
/* rid myself of this line */
830
last->prev->next = last->next;
831
if (last->next)
832
last->next->prev = last->prev;
833
dec_line_numbers(last->next);
834
sym->num_lines--;
835
free(last->buffer);
836
free(last);
837
redraw_win();
838
}
839
else
840
update_inputsymbol(sym);
841
842
}
843
844
static int
845
move_back_one_char(InputItem *sym)
846
{
847
char c = '\000', d = '\000';
848
int dl = 0;
849
850
/* This routine moves all the characters back one */
851
LineStruct *line = sym->curr_line;
852
853
if (line->len > sym->size)
854
c = move_rest_back(line->next, sym->size);
855
856
line->changed = 1;
857
858
if (line->buff_pntr == 0) { /* I am at the front of the line */
859
if (line->prev == 0) {
860
BeepAtTheUser();
861
return 0;
862
}
863
else if (line->prev->len <= sym->size) {
864
back_over_eoln(sym);
865
return 1;
866
}
867
else if (line->len > 0) {
868
d = line->buffer[0];
869
if (line->len <= sym->size) {
870
strncpy(line->buffer, &(line->buffer[1]), line->len - 1);
871
if (c == 0) {
872
line->len--;
873
line->buffer[line->len] = 0;
874
}
875
else
876
line->buffer[line->len - 1] = c;
877
}
878
else {
879
strncpy(line->buffer, &(line->buffer[1]), sym->size - 2);
880
if (c == 0) {
881
line->buffer[sym->size - 1] = 0;
882
line->len--;
883
}
884
else {
885
line->buffer[sym->size - 1] = c;
886
}
887
}
888
}
889
else {
890
/* the line is just going to be thrown away */
891
if (line->next)
892
line->next->prev = line->prev;
893
line->prev->next = line->next;
894
dec_line_numbers(line->next);
895
sym->num_lines--;
896
free(line->buffer);
897
free(line);
898
dl = 1;
899
}
900
c = d;
901
sym->curr_line = line = line->prev;
902
line->changed = 1;
903
line->buff_pntr = sym->size;
904
}
905
906
907
if (line->len <= sym->size) {
908
strncpy(&line->buffer[line->buff_pntr - 1],
909
&(line->buffer[line->buff_pntr]),
910
line->len - line->buff_pntr);
911
if (c == 0)
912
line->buffer[--line->len] = 0;
913
else
914
line->buffer[line->len - 1] = c;
915
}
916
else {
917
strncpy(&(line->buffer[line->buff_pntr - 1]),
918
&(line->buffer[line->buff_pntr]),
919
sym->size - line->buff_pntr);
920
if (c == 0) {
921
line->buffer[sym->size - 1] = 0;
922
line->len = sym->size - 1;
923
}
924
else {
925
if (line->next->len == 0) {
926
line->buffer[sym->size] = 0;
927
line->len = sym->size;
928
}
929
line->buffer[sym->size - 1] = c;
930
}
931
}
932
line->buff_pntr--;
933
if (dl)
934
redraw_win();
935
else
936
update_inputsymbol(sym);
937
return 1;
938
}
939
940
static void
941
back_over_char(InputItem *sym)
942
{
943
if (move_back_one_char(sym))
944
update_inputsymbol(sym);
945
}
946
947
static void
948
delete_eoln(InputItem *sym)
949
{
950
/* much the same as back_over eoln except my perspective has changed */
951
char buff[1024];
952
LineStruct *trace;
953
LineStruct *last = 0;
954
char *tr = buff;
955
int bp;
956
int size = sym->size;
957
958
/* copy all the stuff into the buffer */
959
for (trace = sym->curr_line->next;
960
trace->len > sym->size; trace = trace->next)
961
for (bp = 0; bp < size; bp++)
962
*tr++ = trace->buffer[bp];
963
964
/* copy the last line */
965
for (bp = 0; bp < trace->len; bp++)
966
*tr++ = trace->buffer[bp];
967
trace->len = 0;
968
*tr = 0;
969
970
/* Now that I have the buffer, let's put it back where it belongs. */
971
last = trace;
972
trace = sym->curr_line;
973
trace->changed = 1;
974
for (bp = trace->len, tr = buff; bp < size && *tr; bp++)
975
trace->buffer[bp] = *tr++;
976
977
if (!*tr)
978
trace->len = bp;
979
else {
980
trace->len = size + 1;
981
trace->buffer[size] = '_';
982
trace->buffer[size + 1] = 0;
983
for (trace = trace->next; *tr;) {
984
for (bp = 0; bp < size && *tr; bp++)
985
trace->buffer[bp] = *tr++;
986
if (*tr) {
987
trace->len = size + 1;
988
trace->changed = 1;
989
trace->buffer[size + 1] = 0;
990
trace->buffer[size] = '_';
991
trace = trace->next;
992
}
993
else {
994
trace->len = bp;
995
trace->buffer[bp] = 0;
996
}
997
}
998
}
999
/* Now once I am here, let me see if I can bag a line */
1000
if (last->len == 0) {
1001
/* rid myself of this line */
1002
last->prev->next = last->next;
1003
if (last->next)
1004
last->next->prev = last->prev;
1005
dec_line_numbers(last->next);
1006
sym->num_lines--;
1007
free(last->buffer);
1008
free(last);
1009
redraw_win();
1010
}
1011
else
1012
update_inputsymbol(sym);
1013
1014
}
1015
1016
static int
1017
delete_one_char(InputItem *sym)
1018
{
1019
char c = '\000';
1020
1021
/* This routine moves all the characters back one */
1022
LineStruct *line = sym->curr_line;
1023
1024
if (line->len > sym->size)
1025
c = move_rest_back(line->next, sym->size);
1026
1027
if (c == 0 && line->len == line->buff_pntr) {
1028
if (line->next == 0) {
1029
BeepAtTheUser();
1030
return 0;
1031
}
1032
else {
1033
delete_eoln(sym);
1034
return 1;
1035
}
1036
}
1037
1038
/*
1039
* let me just try to do the copy and put the stupid character c if it
1040
* exists at the end
1041
*/
1042
if (line->len <= sym->size) {
1043
strncpy(&line->buffer[line->buff_pntr],
1044
&(line->buffer[line->buff_pntr + 1]),
1045
line->len - line->buff_pntr);
1046
if (c == 0)
1047
line->buffer[--line->len] = 0;
1048
else
1049
line->buffer[line->len - 1] = c;
1050
}
1051
else {
1052
strncpy(&(line->buffer[line->buff_pntr]),
1053
&(line->buffer[line->buff_pntr + 1]),
1054
sym->size - line->buff_pntr);
1055
if (c == 0) {
1056
line->buffer[sym->size - 1] = 0;
1057
line->len = sym->size - 1;
1058
}
1059
else {
1060
if (line->next->len == 0) {
1061
line->buffer[sym->size] = 0;
1062
line->len = sym->size;
1063
}
1064
line->buffer[sym->size - 1] = c;
1065
}
1066
}
1067
line->changed = 1;
1068
return 1;
1069
}
1070
1071
static void
1072
delete_char(InputItem *sym)
1073
{
1074
if (delete_one_char(sym))
1075
update_inputsymbol(sym);
1076
}
1077
1078
static void
1079
tough_enter(InputItem *sym)
1080
{
1081
char buff[1024];
1082
1083
/*
1084
* This routine takes all the characters from the current cursor
1085
* on, and copies them into a temp buffer, from which they are recopied
1086
* back starting at the next line.
1087
*/
1088
1089
LineStruct *trace;
1090
LineStruct *last = 0;
1091
LineStruct *newline;
1092
char *tr = buff;
1093
int bp = sym->curr_line->buff_pntr;
1094
int size = sym->size;
1095
1096
/* Copy the stuff from the current line */
1097
for (; bp < size; bp++)
1098
*tr++ = sym->curr_line->buffer[bp];
1099
1100
/* now get the stuff from the rest of the lines */
1101
for (trace = sym->curr_line->next;
1102
trace->len > sym->size; trace = trace->next)
1103
for (bp = 0; bp < size; bp++)
1104
*tr++ = trace->buffer[bp];
1105
1106
/* copy the last line */
1107
for (bp = 0; bp < trace->len; bp++)
1108
*tr++ = trace->buffer[bp];
1109
*tr = 0;
1110
1111
/* Now that I have the buffer, let's put it back where it belongs. */
1112
last = trace;
1113
trace = sym->curr_line;
1114
trace->len = trace->buff_pntr;
1115
trace->buffer[trace->len] = 0;
1116
trace->changed = 1;
1117
1118
tr = buff;
1119
for (trace = trace->next; trace != last; trace = trace->next) {
1120
for (bp = 0; bp < size; bp++)
1121
trace->buffer[bp] = *tr++;
1122
trace->len = size + 1;
1123
trace->buffer[size + 1] = 0;
1124
trace->buffer[size] = '_';
1125
trace->changed = 1;
1126
}
1127
1128
/* Once I am here, I should be able to copy this last line */
1129
for (bp = 0; bp < size && *tr; bp++)
1130
trace->buffer[bp] = *tr++;
1131
trace->changed = 1;
1132
1133
/* If I still have more to copy, then do so onto a new line */
1134
if (*tr) {
1135
trace->len = size + 1;
1136
trace->buffer[size + 1] = 0;
1137
trace->buffer[size] = '_';
1138
newline = alloc_inputline(size);
1139
sym->num_lines++;
1140
newline->line_number = last->line_number + 1;
1141
inc_line_numbers(newline->next);
1142
for (bp = 0; *tr; bp++)
1143
newline->buffer[bp] = *tr++;
1144
newline->len = bp;
1145
newline->next = last->next;
1146
newline->prev = last;
1147
last->next = newline;
1148
if (newline->next)
1149
newline->next->prev = newline;
1150
}
1151
else {
1152
trace->len = bp;
1153
trace->buffer[bp] = 0;
1154
}
1155
/* Last but not least change the curr_line */
1156
sym->curr_line = sym->curr_line->next;
1157
sym->curr_line->buff_pntr = 0;
1158
}
1159
1160
static void
1161
enter_new_line(InputItem *sym)
1162
{
1163
LineStruct *newline;
1164
LineStruct *trace;
1165
LineStruct *prev;
1166
LineStruct *line = sym->curr_line;
1167
int bp = line->buff_pntr;
1168
int l = line->len;
1169
int size = sym->size;
1170
1171
/*
1172
* At this point the user has hit a return. Let me just be naive, and
1173
* take everything from the current spot on, and put it on a new line
1174
*/
1175
1176
if (bp == 0) {
1177
if (line->prev->len > size) {
1178
/* just add a return to the end of the last line */
1179
prev = line->prev;
1180
prev->buffer[size] = 0;
1181
prev->len = size;
1182
prev->changed = 1;
1183
}
1184
else {
1185
newline = alloc_inputline(size);
1186
newline->next = sym->curr_line;
1187
newline->prev = sym->curr_line->prev;
1188
line->prev = newline;
1189
sym->num_lines++;
1190
if (newline->prev)
1191
newline->prev->next = newline;
1192
newline->len = newline->buff_pntr = 0;
1193
newline->line_number = line->line_number;
1194
if (sym->curr_line == sym->lines)
1195
sym->lines = newline;
1196
for (trace = newline->next; trace != 0; trace = trace->next)
1197
trace->line_number++;
1198
}
1199
}
1200
else if (bp == size &&
1201
line->len > size) {
1202
/* line->next; */
1203
newline = alloc_inputline(size);
1204
if (line->next)
1205
line->next->prev = newline;
1206
newline->prev = sym->curr_line;
1207
line->next = newline;
1208
newline->len = 0;
1209
newline->buff_pntr = 0;
1210
sym->num_lines++;
1211
sym->curr_line = newline;
1212
newline->line_number = newline->prev->line_number + 1;
1213
for (trace = newline->next; trace != 0; trace = trace->next)
1214
trace->line_number++;
1215
}
1216
else {
1217
if (line->len > size)
1218
tough_enter(sym);
1219
else {
1220
newline = alloc_inputline(size);
1221
strncpy(newline->buffer, &sym->curr_line->buffer[bp], l - bp);
1222
sym->curr_line->len = bp;
1223
sym->curr_line->buffer[bp] = '\0';
1224
newline->next = sym->curr_line->next;
1225
if (sym->curr_line->next)
1226
sym->curr_line->next->prev = newline;
1227
newline->prev = sym->curr_line;
1228
sym->curr_line->next = newline;
1229
newline->len = l - bp;
1230
newline->buff_pntr = 0;
1231
sym->num_lines++;
1232
sym->curr_line = newline;
1233
newline->line_number = newline->prev->line_number + 1;
1234
for (trace = newline->next; trace != 0; trace = trace->next)
1235
trace->line_number++;
1236
}
1237
}
1238
redraw_win();
1239
}
1240
1241
void
1242
dialog(XEvent *event, KeySym keysym, char *buffer)
1243
{
1244
InputItem *item;
1245
1246
item = gWindow->page->current_item;
1247
if (item == 0) {
1248
if (!((keysym >= XK_Shift_L) && (keysym <= XK_Hyper_R)))
1249
/** if something other than a modifier key was hit **/
1250
BeepAtTheUser();
1251
return;
1252
}
1253
1254
1255
/*
1256
* First check if the user had hit an enter key
1257
*/
1258
1259
if ((keysym == XK_Return) || (keysym == XK_KP_Enter))
1260
enter_new_line(item);
1261
/*
1262
* Else did the user actual type a character I can understand
1263
*/
1264
1265
else if (((keysym >= XK_KP_Space) && (keysym <= XK_KP_9))
1266
|| ((keysym >= XK_space) && (keysym <= XK_asciitilde)))
1267
{
1268
/* only handle normal keys */
1269
1270
if (event->xkey.state & UnsupportedModMask)
1271
BeepAtTheUser();
1272
else
1273
add_buffer_to_sym(buffer, item);
1274
}
1275
1276
else if ((keysym >= XK_Shift_L) && (keysym <= XK_Hyper_R))
1277
;
1278
1279
/*
1280
* do nothing, a modifier was hit
1281
*/
1282
1283
else if ((keysym >= XK_F2) && (keysym <= XK_F35)) {
1284
1285
/*
1286
* A function key was hit
1287
*/
1288
1289
if (strlen(buffer) == 0)
1290
BeepAtTheUser();
1291
else
1292
/* If I got characters then add it to the buffer */
1293
1294
add_buffer_to_sym(buffer, item);
1295
}
1296
else
1297
switch (keysym) {
1298
case XK_Escape:
1299
if (event->xkey.state & ModifiersMask)
1300
BeepAtTheUser();
1301
else {
1302
move_cursor_home(item);
1303
delete_rest_of_line(item);
1304
}
1305
break;
1306
case XK_F1:
1307
if (event->xkey.state & ModifiersMask)
1308
BeepAtTheUser();
1309
else {
1310
gWindow->page->helppage = alloc_string(InputAreaHelpPage);
1311
helpForHyperDoc();
1312
}
1313
break;
1314
case XK_Up:
1315
if (event->xkey.state & ModifiersMask)
1316
BeepAtTheUser();
1317
else
1318
move_cursor_up(item);
1319
break;
1320
case XK_Down:
1321
if (event->xkey.state & ModifiersMask)
1322
BeepAtTheUser();
1323
else
1324
move_cursor_down(item);
1325
break;
1326
case XK_Delete:
1327
if (event->xkey.state & ModifiersMask)
1328
BeepAtTheUser();
1329
else
1330
delete_char(item);
1331
break;
1332
case XK_BackSpace:
1333
if (event->xkey.state & ModifiersMask)
1334
BeepAtTheUser();
1335
else
1336
back_over_char(item);
1337
break;
1338
case XK_Left:
1339
if (event->xkey.state & ModifiersMask)
1340
BeepAtTheUser();
1341
else
1342
move_cursor_backward(item);
1343
break;
1344
case XK_Right:
1345
if (event->xkey.state & ModifiersMask)
1346
BeepAtTheUser();
1347
else
1348
move_cursor_forward(item);
1349
break;
1350
case XK_Insert:
1351
if (event->xkey.state & ModifiersMask)
1352
BeepAtTheUser();
1353
else {
1354
gInInsertMode = ((gInInsertMode) ? (0) : (1));
1355
item->curr_line->changed = 1;
1356
update_inputsymbol(item);
1357
}
1358
break;
1359
case XK_Home:
1360
if (event->xkey.state & ModifiersMask)
1361
BeepAtTheUser();
1362
else
1363
move_cursor_home(item);
1364
break;
1365
case XK_End:
1366
if (event->xkey.state & ControlMask)
1367
/* delete from here to the end of the line */
1368
1369
delete_rest_of_line(item);
1370
else if (event->xkey.state & ModifiersMask)
1371
BeepAtTheUser();
1372
else
1373
move_cursor_end(item);
1374
break;
1375
default:
1376
BeepAtTheUser();
1377
break;
1378
}
1379
}
1380
1381