/* SMARTEDIT - A general purpose editor for text files. Copyright (C) 1999 Prashant TR B-42, Kudremukh Colony, II Block, Koramangala, Bangalore - 560034. This program is freeware. You are free to modify and/or redistribute them under the terms of the GNU General Public License version 2.0 or later. Read the file COPYING for the license. The file COPYING.TR contains details about the distribution of this software. */ /* ID for this file. */ #define _MENUFNS_C_ #include "editor.h" #include extern WINDOW *win; extern unsigned video_base; extern PREFERENCES pref; extern WINDOW winlist[]; int winnum = -1; int blocking = 0; /* 1 = Modify top, 2 = modify bottom */ /* File operation error. */ void fileerr() { char buffer[4000]; /* Save display contents. */ movedata(_dos_ds, video_base, FP_SEG(buffer), FP_OFF(buffer), 4000); /* Draw the dialog box. */ drawdialog("Error Reading/Writing to file", 10, 9, 70, 14, BLACK, LIGHTGRAY); textcolor(BLACK); textbackground(WHITE); gotoxy(14, 11); cprintf("An error occurred while trying to read/write"); gotoxy(14, 12); cprintf("from the file. Press any key to continue ..."); _setcursortype(0); if (!getch()) getch(); movedata(FP_SEG(buffer), FP_OFF(buffer), _dos_ds, video_base, 4000); if (win -> insert) _setcursortype(1); else _setcursortype(2); setcursor; win -> dirty = 0; } /* Dirty save file. */ void dirty_savefile() { char buffer[4000]; int key = 0; /* Save display contents. */ movedata(_dos_ds, video_base, FP_SEG(buffer), FP_OFF(buffer), 4000); /* Draw the dialog box. */ if (strcmp(win -> filename, "")) drawdialog(win -> filename, 10, 12, 70, 17, BLACK, LIGHTGRAY); else drawdialog("Window without filename", 10, 12, 70, 17, BLACK, LIGHTGRAY); textcolor(BLACK); textbackground(WHITE); gotoxy(14, 14); cprintf("Latest changes to buffer have not been saved."); gotoxy(14, 15); cprintf("Save now (Y/N) ? ( )"); gotoxy(32, 15); _setcursortype(1); while ((toupper(key) != 'Y') && (toupper(key) != 'N')) { key = getch(); if (!key) getch(); } if (toupper(key) == 'Y') send_message(316); /* Force F2. */ movedata(FP_SEG(buffer), FP_OFF(buffer), _dos_ds, video_base, 4000); if (win -> insert) _setcursortype(1); else _setcursortype(2); setcursor; win -> dirty = 0; } /* New file. */ void File_New() { TEXT *ptr = win -> topline -> next, *ptr1; /* Take action if dirty. */ if (win -> dirty) dirty_savefile(); while (ptr != NULL) { ptr1 = ptr -> next; free(ptr); ptr = ptr1; } win -> scrline = win -> topline; win -> currline = win -> topline; win -> topline -> next = NULL; win -> logicalcol = 1; win -> logicalcolstart = 1; win -> physicalcol = win -> x1 + 1; win -> logicalrow = 1; win -> physicalrow = win -> y1 + 1; win -> dirty = 0; win -> total_lines = 1; /* Destroy block. */ win -> bl1 = win -> bl2 = NULL; win -> bx1 = win -> by1 = win -> bx2 = win -> by2 = 0xffff; strcpy(win -> filename, ""); memset(win -> topline -> text, 32, 256); win -> topline -> text[255] = 0; drawwindow(); redrawwindow(); setcursor; } /* Read a file from the disk. */ /* Returns 0 if error occurred. */ /* Returns -1 if completely loaded. */ int File_Load(char *filename) { char buffer[258]; TEXT *ptr = win -> topline, *node; FILE *fp; unsigned short f, g, bufptr; /* See if dirty. */ if (win -> dirty) dirty_savefile(); /* Erase old contents first. */ File_New(); memset(buffer, 32, 256); buffer[255] = 0; fp = fopen(filename, "rb"); if (fp == NULL) { fileerr(); return 0; } while (fgets(buffer, 255, fp) != NULL) { f = 255; buffer[f--] = 0; f = strlen(buffer); if (f != 255) buffer[f] = 0; /* Create new node. */ node = newnode(); /* Remove non-printable characters. */ f = bufptr = 0; while ((buffer[f]) && (bufptr != 255)) { if (isprint(buffer[f])) ptr -> text[bufptr++] = buffer[f]; else if (buffer[f] == '\t') { if (bufptr < 255 - pref.tabsize) { for(g = 0; g < pref.tabsize; g++) node -> text[bufptr++] = ' '; } } f++; } /* Setup the links. */ win -> currline -> next = node; node -> next = NULL; node -> prev = win -> currline; win -> currline = node; ptr = win -> currline; memset(buffer, 32, 256); buffer[255] = 0; win -> total_lines++; } win -> logicalrow = 1; win -> logicalcol = 1; win -> physicalrow = win -> y1 + 1; win -> physicalcol = win -> x1 + 1; win -> logicalcolstart = 1; win -> currline = win -> topline; win -> scrline = win -> topline; win -> dirty = 0; strcpy(win -> filename, filename); strupr(win -> filename); fclose(fp); /* Clear dirty flag. */ win -> dirty = 0; drawwindow(); redrawwindow(); setcursor; return -1; } /* Write a file from the disk. */ /* Returns 0 if error occurred. */ /* Returns -1 if completely written. */ int File_Save(char *filename) { char drive[2], name[9], ext[4], dir[256], buffer[256]; TEXT *ptr = win -> topline; FILE *fp; unsigned short pos; fp = fopen(filename, "wb"); if (fp == NULL) { fileerr(); return 0; } while (ptr != NULL) { /* Remove blanks at the end of line. */ pos = 254; while ((pos != 0xffff) && (ptr -> text[pos] == 32)) pos--; ptr -> text[++pos] = 0; if (fputs(ptr -> text, fp) == EOF) { fclose(fp); fileerr(); return 0; } ptr -> text[pos] = 32; /* Put newline and return characters. */ if (pref.unixstyle) fputs("\n", fp); else fputs("\r\n", fp); ptr = ptr -> next; } fclose(fp); strcpy(win -> filename, filename); strupr(win -> filename); /* See if we need to backup. */ if (pref.backupfiles) { ptr = win -> topline; fnsplit(filename, drive, dir, name, ext); fnmerge(buffer, drive, dir, name, "BAK"); fp = fopen(buffer, "wb"); if (fp == NULL) { fileerr(); return 0; } while (ptr != NULL) { /* Remove blanks at the end of line. */ pos = 254; while ((pos != 0xffff) && (ptr -> text[pos] == 32)) pos--; ptr -> text[++pos] = 0; if (fputs(ptr -> text, fp) == EOF) { fclose(fp); return 0; } ptr -> text[pos + 1] = 32; /* Put newline and return characters. */ if (pref.unixstyle) fputs("\n", fp); else fputs("\r\n", fp); ptr = ptr -> next; } fclose(fp); } /* Clear dirty flag. */ win -> dirty = 0; drawwindow(); redrawwindow(); setcursor; return -1; } void File_SaveConfigError() { char buffer[4000]; /* Save display contents. */ movedata(_dos_ds, video_base, FP_SEG(buffer), FP_OFF(buffer), 4000); /* Draw the dialog box. */ drawdialog("Error !", 10, 8, 70, 17, BLACK, LIGHTGRAY); textcolor(BLACK); textbackground(WHITE); gotoxy(12, 10); cprintf("SMARTEDIT was not able to save the configuration"); gotoxy(12, 11); cprintf("file EDITOR.CFG due to some reason. Changes"); gotoxy(12, 13); cprintf("made to the preferences will be temporary."); gotoxy(29, 15); cprintf("Press any key to return"); _setcursortype(0); if (!getch()) getch(); movedata(FP_SEG(buffer), FP_OFF(buffer), _dos_ds, video_base, 4000); if (win -> insert) _setcursortype(1); else _setcursortype(2); setcursor; } /* Save configuration. */ int File_SaveConfig() { FILE *fp; if ((fp = fopen("editor.cfg", "wb")) == NULL) return 0; else { fwrite(&pref, sizeof(PREFERENCES), 1, fp); fclose(fp); return 1; } } /* Print the document. */ int File_Print() { TEXT *ptr = win -> topline; unsigned short pos; while (ptr != NULL) { /* Remove blanks at the end of line. */ pos = 254; while ((pos != 0xffff) && (ptr -> text[pos] == 32)) pos--; ptr -> text[++pos] = 0; if (fputs(ptr -> text, stdprn) == EOF) return 0; /* Put newline and return characters. */ fputs("\r\n", stdprn); ptr = ptr -> next; } return -1; } /* DOS Shell. */ void File_DOSShell() { textcolor(LIGHTGRAY); textbackground(BLACK); clrscr(); printf("Type EXIT and press to return to SMARTEDIT.\n"); system("command.com"); textmode(pref.textmode); textcolor(pref.color); textbackground(pref.bkcolor); clrscr(); intensevideo(); mainmenubar(); drawwindow(); redrawwindow(); setcursor; } void File_ExecDOSCmd() { char cmd[256]; doscmd_dialog(cmd); if (!strcmp(cmd, "")) { setcursor; return; } textcolor(LIGHTGRAY); textbackground(BLACK); clrscr(); printf("Running DOS Command through SMARTEDIT.\n"); system(cmd); printf("Press and key to return to SMARTEDIT.\n"); if (!getch()) getch(); textmode(pref.textmode); textcolor(pref.color); textbackground(pref.bkcolor); clrscr(); intensevideo(); mainmenubar(); drawwindow(); redrawwindow(); setcursor; } /* Exit from program. */ void File_Exit() { TEXT *temp; Window_CloseAll(); /* Delete the last window. */ if (win -> dirty) dirty_savefile(); temp = win -> topline; while (temp != NULL) { win -> topline = win -> topline -> next; free(temp); temp = win -> topline; } exit(0); } /* Search for string. */ /* Returns 0 if not found, -1 if found. */ int Search_Find(char *text) { unsigned short found = FALSE; TEXT *ptr = win -> currline; unsigned short row = 1, prow = win -> y1 + 1; char *result; /* For the 1st line. */ if ((result = (char *)strstr(&ptr -> text[win -> logicalcol], text)) != NULL) { /* Setup structures. */ win -> logicalcol = FP_OFF(result) - FP_OFF(ptr -> text) + 1; win -> physicalcol = (win -> logicalcol - 1) % (win -> x2 - win -> x1 - 1) + win -> x1 + 1; win -> logicalcolstart = (win -> logicalcol - 1) / (win -> x2 - win -> x1 - 1) + 1; redrawline(); setcursor; return -1; } /* Get row position. */ if (win -> currline -> next == NULL) return 0; ptr = win -> topline; while (ptr != win -> currline -> next) { ptr = ptr -> next; row++; prow = (++prow > win -> y2 - 1) ? win -> y1 + 1: prow; } /* Search the remaining list. */ while ((ptr != NULL) && (!found)) { if ((result = (char *)strstr(ptr -> text, text)) != NULL) { /* We have found the string. */ win -> logicalrow = row; win -> logicalcol = FP_OFF(result) - FP_OFF(ptr -> text) + 1; win -> physicalrow = ++prow; win -> physicalcol = (win -> logicalcol - 1) % (win -> x2 - win -> x1 - 1) + win -> x1 + 1; win -> logicalcolstart = (win -> logicalcol - 1) / (win -> x2 - win -> x1 - 1) + 1; found = TRUE; } else { ptr = ptr -> next; row++; prow = (++prow > win -> y2 - 1) ? win -> y1 + 1 : prow; } } if (ptr == NULL) return 0; win -> scrline = ptr; prow = (prow > win -> y2 - 1) ? win -> y1 + 1 : prow; while ((--prow > win -> y1) && (win -> scrline -> prev != NULL)) win -> scrline = win -> scrline -> prev; win -> physicalrow -= prow - win -> y1; if (win -> physicalrow > win -> y2 - 1) win -> physicalrow = win -> y1 + 1; win -> currline = ptr; win -> bl1 = win -> currline; win -> bl2 = win -> currline; win -> bx1 = win -> logicalcol; win -> bx2 = win -> logicalcol + strlen(text); win -> by1 = win -> by2 = win -> logicalrow; redrawwindow(); setcursor; return -1; } /* Replace string. */ /* Returns 0 if not found, -1 if found. */ int Search_Replace(char *text, char *newtxt) { unsigned short found = FALSE, f, g; TEXT *ptr = win -> currline; unsigned short row = 1, prow = win -> y1 + 1; char *result; /* For the 1st line. */ if ((result = (char *)strstr(&ptr -> text[win -> logicalcol], text)) != NULL) { /* Setup structures. */ win -> logicalcol = FP_OFF(result) - FP_OFF(ptr -> text) + 1; win -> physicalcol = (win -> logicalcol - 1) % (win -> x2 - win -> x1 - 1) + win -> x1 + 1; win -> logicalcolstart = (win -> logicalcol - 1) / (win -> x2 - win -> x1 - 1) + 1; redrawline(); setcursor; return -1; } /* Get row position. */ if (win -> currline -> next == NULL) return 0; ptr = win -> topline; while (ptr != win -> currline -> next) { ptr = ptr -> next; row++; prow = (++prow > win -> y2 - 1) ? win -> y1 + 1: prow; } /* Search the remaining list. */ while ((ptr != NULL) && (!found)) { if ((result = (char *)strstr(ptr -> text, text)) != NULL) { /* We have found the string. */ win -> logicalrow = row; win -> logicalcol = FP_OFF(result) - FP_OFF(ptr -> text) + 1; win -> physicalrow = ++prow; win -> physicalcol = (win -> logicalcol - 1) % (win -> x2 - win -> x1 - 1) + win -> x1 + 1; win -> logicalcolstart = (win -> logicalcol - 1) / (win -> x2 - win -> x1 - 1) + 1; found = TRUE; } else { ptr = ptr -> next; row++; prow = (++prow > win -> y2 - 1) ? win -> y1 + 1: prow; } } if (ptr == NULL) return 0; win -> scrline = ptr; prow = (prow > win -> y2 - 1) ? win -> y1 + 1 : prow; while ((--prow > win -> y1) && (win -> scrline -> prev != NULL)) win -> scrline = win -> scrline -> prev; win -> physicalrow -= prow - win -> y1; if (win -> physicalrow > win -> y2 - 1) win -> physicalrow = win -> y1 + 1; win -> currline = ptr; /* Replace the text. */ /* First see if the text can fit in the 255 byte limit. */ /* Calculate length. */ g = 254; while (ptr-> text[g] == 32) g--; g++; if (strlen(newtxt) < strlen(text)) { /* Blank pad the rest of the characters. */ for(f = 0; f < strlen(text); f++) ptr -> text[win -> logicalcol + f - 1] = ' '; } /* Make space for new entry. */ memmove(&ptr -> text[win -> logicalcol + strlen(newtxt) - 1], &ptr -> text[win -> logicalcol + strlen(text) - 1], g - win -> logicalcol + (abs(- strlen(text) + strlen(newtxt))) + 1); ptr -> text[strlen(ptr -> text)] = 32; ptr -> text[255] = 0; /* Write the new entry. */ for(f = 0; f < strlen(newtxt); f++) ptr -> text[win -> logicalcol + f - 1] = newtxt[f]; win -> bl1 = win -> currline; win -> bl2 = win -> currline; win -> bx1 = win -> logicalcol; win -> bx2 = win -> logicalcol + strlen(newtxt); win -> by1 = win -> by2 = win -> logicalrow; /* Set dirty flag. */ win -> dirty = 1; redrawwindow(); setcursor; return -1; } /* Goto a line number. */ void Search_gotoline(unsigned short line_no) { TEXT *ptr = win -> topline; int row = 1, prow = win -> y1 + 1; if (!line_no--) return; while ((line_no--) && (ptr -> next != NULL)) { row++; prow = (++prow > win -> y2 - 1) ? win -> y1 + 1: prow; ptr = ptr -> next; } if (ptr == NULL) return; win -> logicalrow = row; win -> physicalrow = prow; win -> currline = ptr; win -> scrline = ptr; while ((--prow > win -> y1) && (win -> scrline -> prev != NULL)) win -> scrline = win -> scrline -> prev; win -> physicalrow -= prow - win -> y1; redrawwindow(); setcursor; } /* Editor preferences. */ void Options_Editor() { char buffer[4000], defname[255], tabstr[5], c, choice = 1; int bkfiles = pref.backupfiles, insmode = pref.insertmode, tabs = pref.tabs, insstat = pref.initinsertmode, tabsize = pref.tabsize, result, unixstyle = pref.unixstyle, scrltype = pref.scrltype; strcpy(defname, ""); strcpy(tabstr, ""); /* Save display contents. */ movedata(_dos_ds, video_base, FP_SEG(buffer), FP_OFF(buffer), 4000); /* Draw the dialog box. */ drawdialog("Editor Preferences", 10, 4, 70, 19, BLACK, LIGHTGRAY); textcolor(BLACK); textbackground(LIGHTGRAY); gotoxy(12, 6); cprintf("[X] Standard scrollbars"); gotoxy(12, 7); cprintf("[X] Create Backup files"); gotoxy(12, 8); cprintf("[X] Insert mode enable/disable"); gotoxy(12, 9); cprintf("[X] Allow Tab Characters"); gotoxy(12, 10); cprintf("[X] Initial INSERT status (ON/OFF)"); gotoxy(12, 11); cprintf("[X] Save files in UNIX style"); gotoxy(12, 13); cprintf("Tab Size: "); textcolor(WHITE); textbackground(BLUE); cprintf("[...]"); textcolor(BLACK); textbackground(LIGHTGRAY); gotoxy(12, 15); cprintf("Default Filename: "); textcolor(WHITE); textbackground(BLUE); cprintf("[..................]"); textcolor(BLACK); textbackground(LIGHTGRAY); gotoxy(21, 17); cprintf("Press Enter to accept or ESC to return"); /* Check current options. */ check(13, 6, pref.scrltype); check(13, 7, pref.backupfiles); check(13, 8, pref.insertmode); check(13, 9, pref.tabs); check(13, 10, pref.initinsertmode); check(13, 11, pref.unixstyle); textcolor(WHITE); textbackground(BLUE); gotoxy(23, 13); cprintf("%d", pref.tabsize); gotoxy(31, 15); if (strlen(pref.deffilename) > 18) { c = pref.deffilename[18]; pref.deffilename[18] = 0; cprintf("%s", pref.deffilename); pref.deffilename[18] = c; } else cprintf("%s", pref.deffilename); textcolor(BLACK); textbackground(LIGHTGRAY); _setcursortype(1); /* Wait for choice. */ result = 0; do { switch (choice) { case 1: gotoxy(13, 6); result = wait_checkbox(&scrltype); break; case 2: gotoxy(13, 7); result = wait_checkbox(&bkfiles); break; case 3: gotoxy(13, 8); result = wait_checkbox(&insmode); break; case 4: gotoxy(13, 9); result = wait_checkbox(&tabs); break; case 5: gotoxy(13, 10); result = wait_checkbox(&insstat); break; case 6: gotoxy(13, 11); result = wait_checkbox(&unixstyle); break; case 7: strcpy(tabstr, ""); textcolor(WHITE); textbackground(BLUE); result = editbox_special(tabstr, 23, 13, 3, 3, '.'); if (strcmp(tabstr, "")) tabsize = atoi(tabstr); if ((tabsize < 1) || (tabsize > 254)) tabsize = 8; gotoxy(23, 13); cprintf("%d", tabsize); textcolor(BLACK); textbackground(LIGHTGRAY); break; case 8: strcpy(defname, ""); textcolor(WHITE); textbackground(BLUE); result = editbox_special(defname, 31, 15, 18, 255, '.'); if (!strcmp(defname, "")) strcpy(defname, pref.deffilename); gotoxy(31, 15); if (strlen(defname) > 18) { c = defname[18]; defname[18] = 0; cprintf("%s", defname); defname[18] = c; } else cprintf("%s", defname); textcolor(BLACK); textbackground(LIGHTGRAY); break; } /* Up arrow. */ if ((result == 328) || (result == 271)) { if (choice == 1) choice = 8; else choice--; } /* Down arrow. */ if ((result == 336) || (result == 9)) { if (choice == 8) choice = 1; else choice++; } /* Setup all options if ENTER pressed. */ if (result == 13) { pref.scrltype = scrltype; pref.backupfiles = bkfiles; pref.insertmode = insmode; pref.initinsertmode = insstat; pref.tabs = tabs; pref.tabsize = tabsize; pref.unixstyle = unixstyle; strcpy(pref.deffilename, defname); strupr(pref.deffilename); break; } /* Ignore options if ESC was pressed. */ if (result == 27) break; } while (1); movedata(FP_SEG(buffer), FP_OFF(buffer), _dos_ds, video_base, 4000); drawwindow(); redrawwindow(); _setcursortype((!win -> insert) + 1); setcursor; } /* Print the help contents. */ void Help_Contents() { char buffer[4000]; /* Save display contents. */ movedata(_dos_ds, video_base, FP_SEG(buffer), FP_OFF(buffer), 4000); /* Draw the dialog box. */ drawdialog("Help Contents", 10, 3, 70, 23, BLACK, LIGHTGRAY); textcolor(BLACK); textbackground(WHITE); gotoxy(34, 5); cprintf("Shortcut keys"); gotoxy(12, 7); cprintf("Ctrl-A: Replace text " "Ctrl-C/PgDn: Page Down"); gotoxy(12, 8); cprintf("Ctrl-D: Char. right " "Ctrl-E: Line Up"); gotoxy(12, 9); cprintf("Ctrl-F: Find text " "Ctrl-G/Del: Delete char"); gotoxy(12, 10); cprintf("Ctrl-H/Bksp: Backspace " "Ctrl-I/Tab: Insert Tab"); gotoxy(12, 11); cprintf("Ctrl-J: Repeat Replace " "Ctrl-L: Repeat Find"); gotoxy(12, 12); cprintf("Ctrl-M/Enter: Insert newline " "Ctrl-R/PgUp: Page Up"); gotoxy(12, 13); cprintf("Ctrl-S: Char. left " "Ctrl-V/Ins: Toggle Insert"); gotoxy(12, 14); cprintf("Ctrl-X: Line Down " "Ctrl-Y: Delete line"); gotoxy(34, 16); cprintf("Functions Keys"); gotoxy(12, 18); cprintf("F1: This Screen " "F2: Save File"); gotoxy(12, 19); cprintf("F3: Load File " "F10: Menu"); gotoxy(29, 21); cprintf("Press any key to return"); _setcursortype(0); if (!getch()) getch(); movedata(FP_SEG(buffer), FP_OFF(buffer), _dos_ds, video_base, 4000); if (win -> insert) _setcursortype(1); else _setcursortype(2); setcursor; } /* Information about the authors. */ void Help_About() { char buffer[4000]; /* Save display contents. */ movedata(_dos_ds, video_base, FP_SEG(buffer), FP_OFF(buffer), 4000); /* Draw the dialog box. */ drawdialog("About SMARTEDIT", 10, 8, 70, 19, BLACK, LIGHTGRAY); textcolor(BLACK); textbackground(WHITE); gotoxy(12, 10); cprintf("SMARTEDIT was written by Prashant TR. This program is"); gotoxy(12, 11); cprintf("a general purpose editor used by many of my software."); gotoxy(12, 13); cprintf("ABSOLUTELY NO WARRANTY! This program is redistributable"); gotoxy(12, 14); cprintf("under the terms of the GNU General Public License. See"); gotoxy(12, 15); cprintf("the file COPYING.TR for more details."); gotoxy(29, 17); cprintf("Press any key to return"); _setcursortype(0); if (!getch()) getch(); movedata(FP_SEG(buffer), FP_OFF(buffer), _dos_ds, video_base, 4000); if (win -> insert) _setcursortype(1); else _setcursortype(2); setcursor; } void blockbegin() { TEXT *txt; int temp; if (!(shiftstatus & 3)) return; /* Shift held. */ blocking = 1; /* New block. */ if (((win -> bx1 == 0xffff) && (win -> bx2 == 0xffff)) || (((win -> by1 != win -> logicalrow) || (win -> bx1 != win -> logicalcol)) && ((win -> by2 != win -> logicalrow) || (win -> bx2 != win -> logicalcol)))) { win -> highlighted = 1; win -> bx1 = win -> bx2 = win -> logicalcol; win -> by1 = win -> by2 = win -> logicalrow; win -> bl1 = win -> bl2 = win -> currline; /* Blocking need not be changed. */ } /* Continuation of block beginning. */ else if ((win -> bx1 == win -> logicalcol) && (win -> by1 == win -> logicalrow)) { win -> highlighted = 1; win -> bl1 = win -> currline; win -> bx1 = win -> logicalcol; win -> by1 = win -> logicalrow; /* Blocking need not be changed. */ } /* Continuation of block ending. */ else if ((win -> bx2 == win -> logicalcol) && (win -> by2 == win -> logicalrow)) { win -> highlighted = 1; win -> bl2 = win -> currline; win -> bx2 = win -> logicalcol; win -> by2 = win -> logicalrow; /* Change blocking. */ blocking = 2; } /* Reverse blocking if necessary. */ if ((win -> by1 > win -> by2) || ((win -> bx1 > win -> bx2) && (win -> by1 == win -> by2))) { temp = win -> bx1; win -> bx1 = win -> bx2; win -> bx2 = temp; temp = win -> by1; win -> by1 = win -> by2; win -> by2 = temp; txt = win -> bl1; win -> bl1 = win -> bl2; win -> bl2 = txt; if (blocking == 2) blocking = 1; else blocking = 2; } } void blockend() { TEXT *txt; int temp; if (!blocking) return; if (blocking == 1) { win -> bl1 = win -> currline; win -> bx1 = win -> logicalcol; win -> by1 = win -> logicalrow; } else if (blocking == 2) { win -> bl2 = win -> currline; win -> bx2 = win -> logicalcol; win -> by2 = win -> logicalrow; } blocking = 0; /* Reverse blocking if necessary. */ if ((win -> by1 > win -> by2) || ((win -> bx1 > win -> bx2) && (win -> by1 == win -> by2))) { temp = win -> bx1; win -> bx1 = win -> bx2; win -> bx2 = temp; temp = win -> by1; win -> by1 = win -> by2; win -> by2 = temp; txt = win -> bl1; win -> bl1 = win -> bl2; win -> bl2 = txt; } redrawwindow(); setcursor; } void Edit_Cut() { int f, max; TEXT *temp; /* Check if anything is highlighted. */ if (!win -> highlighted) return; /* See if we have a block, we should - but just in case ... */ if ((win -> bl1 == NULL) || (win -> bl2 == NULL)) return; /* We may have selected blank spaces at the end. Checkup that. */ max = 254; while (win -> bl1 -> text[max] == 32) max--; max += 2; if ((win -> bx1 > max) && (win -> by1 == win -> by2)) { destroyblock(); redrawwindow(); return; } if (win -> bx2 > max) win -> bx2 = max; /* Delete the contents. */ /* Forget the 1st and last lines for now. */ win -> currline = win -> bl1; if ((win -> by1 != win -> by2) && (win -> bl1 -> next != win -> bl2)) { /* Delete all lines in the middle. */ temp = win -> bl1 -> next; while (temp != win -> bl2) { temp = temp -> next; free(temp -> prev); /* Change line count. */ win -> total_lines--; } win -> bl1 -> next = win -> bl2; win -> bl2 -> prev = win -> bl1; } if (win -> bl1 != win -> bl2) { /* Destroy portion of the line. */ memccpy(&win -> bl1 -> text[win -> bx1 - 1], &win -> bl1 -> text[max - 1], 0, 255); /* Blank pad and cut off at 255. */ win -> bl1 -> text[strlen(win -> bl1 -> text)] = 32; win -> bl1 -> text[255] = 0; /* Delete the last line. */ /* We may have selected blank spaces at the end. Checkup that. */ max = 254; while (win -> bl2 -> text[max] == 32) max--; max += 2; if (win -> bx2 > max) win -> bx2 = max; /* Destroy portion of the line. */ memccpy(win -> bl2 -> text, &win -> bl2 -> text[win -> bx2 - 1], 0, 255); /* Blank pad and cut off at 255. */ win -> bl2 -> text[strlen(win -> bl2 -> text)] = 32; win -> bl2 -> text[255] = 0; } /* Reset figures. */ win -> logicalrow = win -> by1; win -> logicalcol = win -> bx1; win -> physicalrow = (win -> logicalrow % (win -> y2 - win -> y1 - 1)) + win -> y1; /* See if the column can be visible in the screen. */ if ((win -> logicalcolstart > win -> bx1) || (win -> bx2 >= win -> logicalcolstart + (win -> x2 - win -> x1 - 1))) { win -> physicalcol = (win -> logicalcol % (win -> x2 - win -> x1 - 1)) + win -> x1; win -> logicalcolstart = (win -> logicalcol % (win -> y2 - win -> y1 - 1)) + win -> y1 + 1; } else win -> physicalcol = win -> logicalcol - win -> logicalcolstart + win -> x1 + 1; /* Change win -> scrline. */ f = win -> physicalrow - win -> y1 - 1; win -> scrline = win -> currline; while (f--) win -> scrline = win -> scrline -> prev; /* Reset blocks. */ win -> highlighted = 0; if (win -> bl1 != win -> bl2) delete_char(); else { max = 254; while (win -> bl2 -> text[max] == 32) max--; max += 2; for(f = win-> bx1; f < win -> bx2; f++) delete_char(); } /* Set dirty flag. */ win -> dirty = 1; destroyblock(); redrawwindow(); setcursor; } void Edit_Copy() { /* Use he clipboard as a singly linked list. */ TEXT *temp = win -> clipboard, *node, *oldclip; /* See if the clipboard has something. */ if (win -> clipboard != NULL) { /* Remove everything from the clipboard. */ while (temp != NULL) { temp = win -> clipboard -> next; free(win -> clipboard); win -> clipboard = temp; } } /* Copy everything into the clipboard. */ win -> clipboard = newnode(); node = win -> clipboard; if (win -> bl1 == win -> bl2) { /* Copy the highlighted contents. */ memcpy(win -> clipboard -> text, &win -> bl1 -> text[win -> bx1 - 1], win -> bx2 - win -> bx1); /* Add NULL. */ win -> clipboard -> text[win -> bx2 - win -> bx1] = 0; win -> clipboard -> next = NULL; } else { /* We have more than one line. */ /* Copy only the 1st line. */ memccpy(win -> clipboard -> text, &win -> bl1 -> text[win -> bx1 - 1], 0, 255); /* Don't remove NULL. */ oldclip = win -> clipboard; /* See if we have to copy lines other than the last line. */ temp = win -> bl1 -> next; while (temp != win -> bl2) { node = newnode(); memccpy(node -> text, temp -> text, 0, 255); oldclip -> next = node; /* Don't remove NULL. */ /* Forget the "prev" link. */ temp = temp -> next; oldclip = node; } if (win -> bx2 != 1) { node = newnode(); /* Copy the last line. */ memccpy(node -> text, win -> bl2 -> text, 0, win -> bx2 - 1); /* Link up to the last line. */ oldclip -> next = node; } node -> next = NULL; } } void Edit_Paste() { unsigned short pos; TEXT *temp = win -> clipboard, *node, *curr = win -> currline, *topnode; /* See if we have a block, we should - but just in case ... */ if (temp == NULL) return; /* Add the contents. */ /* We don't have to position the cursor. We are already there. */ /* Don't simulate this. Directly add to list. */ if (temp -> next != NULL) { node = newnode(); topnode = node; node -> prev = curr -> prev; node -> next = NULL; memccpy(node -> text, temp -> text, 0, 255); temp = temp -> next; /* Change line count. */ win -> total_lines++; while (temp != NULL) { node -> next = newnode(); node -> next -> prev = node; node = node -> next; memccpy(node -> text, temp -> text, 0, 255); node -> next = NULL; temp = temp -> next; /* Change line count. */ win -> total_lines++; } node -> next = curr; if (curr -> prev != NULL) curr -> prev -> next = topnode; else win -> topline = topnode; curr -> prev = node; win -> currline = topnode; redrawwindow(); setcursor; } else { /* Insert a piece of text. */ /* We can use insert_char(). */ for(pos = 0; pos < strlen(temp -> text); pos++) insert_char(temp -> text[pos]); } /* Set dirty flag. */ win -> dirty = 1; } void Edit_Clear() { TEXT *temp = win -> clipboard; /* Empty the clipboard. */ if (win -> clipboard != NULL) { while (temp != NULL) { temp = win -> clipboard -> next; free(win -> clipboard); win -> clipboard = temp; } } Edit_Cut(); destroyblock(); /* Set dirty flag. */ win -> dirty = 1; } void clrscr_direct() { unsigned short offset = 320, attrib = (pref.bkcolor << 4) | pref.color; while (offset < 3840) { _farpokeb(_dos_ds, video_base + offset++, 32); _farpokeb(_dos_ds, video_base + offset++, attrib); } } void Window_Size() { int result; clrscr_direct(); drawwindow(); redrawwindow(); do { textcolor(pref.statusbarcolor); textbackground(pref.statusbarbkcolor); gotoxy(1, 25); clreol(); cprintf(" Press arrow keys to move / SHIFT+arrow keys" " to size and press ENTER."); if (!(result = wait())) result += 256 + getch(); if (result == 256 + 'H') { if (shiftstatus & 3) { if (win -> y1 < win -> y2 - 5) win -> y2--; } else if (win -> y1 > 3) { win -> y1--; win -> y2--; win -> physicalrow--; } clrscr_direct(); drawwindow(); redrawwindow(); } if (result == 256 + 'P') { if (shiftstatus & 3) { if (win -> y2 < 24) win -> y2++; } else if (win -> y2 < 24) { win -> y1++; win -> y2++; win -> physicalrow++; } clrscr_direct(); drawwindow(); redrawwindow(); } if (result == 256 + 'K') { if (shiftstatus & 3) { if (win -> x1 < win -> x2 - 26) win -> x2--; } else if (win -> x1 > 1) { win -> x1--; win -> x2--; win -> physicalcol--; } clrscr_direct(); drawwindow(); redrawwindow(); } if (result == 256 + 'M') { if (shiftstatus & 3) { if (win -> x2 < 80) win -> x2++; } else if (win -> x2 < 80) { win -> x1++; win -> x2++; win -> physicalcol++; } clrscr_direct(); drawwindow(); redrawwindow(); } } while (result != 13); mainmenubar(); /* Ctrl-PgUp. */ send_message(388); setcursor; } void Window_FullScreen() { /* Set window to full screen. */ win -> x1 = 1; win -> x2 = 80; win -> y1 = 3; win -> y2 = 24; /* Ctrl-PgUp. */ send_message(388); drawwindow(); redrawwindow(); mainmenubar(); setcursor; } void Window_NewWindow() { int f; for(f = 0; f < MAXWINDOWS; f++) if (!winlist[f].in_use) break; if (f == MAXWINDOWS) return; /* Create a new window. */ /* win = (WINDOW *)malloc(sizeof(WINDOW));*/ winnum = f; win = &winlist[winnum]; win -> x1 = 1; win -> y1 = 3; win -> x2 = 80; win -> y2 = 24; win -> logicalrow = 1; win -> logicalcol = 1; win -> logicalcolstart = 1; win -> physicalrow = win -> y1 + 1; win -> physicalcol = win -> x1 + 1; win -> total_lines = 1; win -> insert = ON; win -> topline = newnode(); win -> topline -> next = win -> topline -> prev = NULL; win -> scrline = win -> topline; win -> currline = win -> topline; win -> dirty = 0; win -> bx1 = win -> by1 = win -> bx2 = win -> by2 = -1; win -> bl1 = win -> bl2 = NULL; win -> clipboard = NULL; strcpy(win -> filename, ""); win -> in_use = 1; drawwindow(); redrawwindow(); setcursor; } void Window_NextWindow() { int f; for(f = winnum + 1; f < MAXWINDOWS; f++) if (winlist[f].in_use) break; if (f == MAXWINDOWS) { for(f = 0; f < winnum; f++) if (winlist[f].in_use) break; if (f == winnum) return; } /* Switch window. */ winnum = f; win = &winlist[winnum]; drawwindow(); redrawwindow(); setcursor; } /* Returns the next window number if current is deleted. */ int check_multiwindow() { int f; /* Check if a window exists after the current window. */ for(f = winnum + 1; f < MAXWINDOWS; f++) if (winlist[f].in_use) return (f); /* Check if another window exists. */ for(f = 0; f < winnum; f++) if (winlist[f].in_use) return(f); /* No more windows. */ return(-1); } void Window_CloseWindow() { int nwin; TEXT *temp; /* See if dirty. */ if (win -> dirty) dirty_savefile(); /* See if extra windows exist. */ nwin = check_multiwindow(); if (nwin == -1) return; /* Delete the current window. */ temp = win -> topline; while (temp != NULL) { win -> topline = temp -> next; free(temp); temp = win -> topline; } win -> in_use = 0; win = &winlist[nwin]; winnum = nwin; drawwindow(); redrawwindow(); setcursor; } void Window_CloseAll() { int f = winnum; /* See if extra windows exist. */ while ((winnum = check_multiwindow()) != -1) { win = &winlist[winnum]; Window_CloseWindow(); win = &winlist[f]; winnum = f; } } int choosecolor(int x, int y, unsigned short *color) { int quit = 0, clr = *color, f, g, key, retval = 1; int ec; _setcursortype(0); do { ec = (clr & 0xf); for(f = 0; f < 4; f++) for(g = 0; g < 4; g++) { gotoxy(x + g * 3, y + f); textcolor(f * 4 + g); cprintf("ÛÛÛ"); gotoxy(x + g * 3, y + f); } gotoxy(x + (ec % 4) * 3, y + (ec / 4)); textcolor(clr); textbackground(BLACK); cprintf("±±±"); key = getch(); if (!key) key += 256 + getch(); if (key == 27) { retval = 0; quit = 1; } if (key == 13) { *color = clr; quit = 1; } if (key == 256 + 'H') { if (clr < 4) clr = 12 + clr; else clr -= 4; } if (key == 256 + 'P') { if (clr > 11) clr = clr % 4; else clr += 4; } if (key == 256 + 'K') { clr--; if (clr < 0) clr = 15; } if (key == 256 + 'M') { clr++; if (clr > 15) clr = 0; } } while (!quit); _setcursortype(0); return (retval); } unsigned short setupcolor(unsigned short *color, unsigned short *bkcolor) { unsigned short result, f, g; unsigned short ec, eb; ec = (*color & 0xf); eb = ((*bkcolor) | ((*color & 128) >> 4)); /* Display color status. */ sngbox_direct(29, 6, 43, 11, BLACK, LIGHTGRAY); for(f = 0; f < 4; f++) for(g = 0; g < 4; g++) { gotoxy(30 + g * 3, 7 + f); textcolor(f * 4 + g); cprintf("ÛÛÛ"); } textcolor(BLACK); textbackground(LIGHTGRAY); gotoxy(32, 13); cprintf("Foreground"); sngbox_direct(49, 6, 63, 11, BLACK, LIGHTGRAY); for(f = 0; f < 4; f++) for(g = 0; g < 4; g++) { gotoxy(50 + g * 3, 7 + f); textcolor(f * 4 + g); cprintf("ÛÛÛ"); } textcolor(BLACK); textbackground(LIGHTGRAY); gotoxy(52, 13); cprintf("Background"); /* Mark foreground and background colors. */ gotoxy(30 + (ec % 4) * 3, 7 + (ec / 4)); textcolor(*color); textbackground(eb); cprintf("±±±"); gotoxy(50 + (eb % 4) * 3, 7 + (eb / 4)); textcolor(*bkcolor); textbackground(ec); cprintf("±±±"); result = wait(); if (!result) result += 256 + getch(); if (result == 13) { if (choosecolor(30, 7, color)) result = 13; else { result = 27; return (result); } if (choosecolor(50, 7, &eb)) result = 13; else result = 27; if ((result == 13) && (eb > 7)) { *bkcolor = eb; *color |= 128; *bkcolor &= 7; } } return (result); } void Options_Desktop() { char buffer[4000]; int choice = 1, result; /* Save display contents. */ movedata(_dos_ds, video_base, FP_SEG(buffer), FP_OFF(buffer), 4000); /* Draw the dialog box. */ _setcursortype(0); drawdialog("Desktop Properties", 4, 3, 76, 21, BLACK, LIGHTGRAY); textcolor(BLACK); textbackground(LIGHTGRAY); gotoxy(32, 19); cprintf("Press ESC to return"); /* Wait for choice. */ result = 0; do { textcolor(BLACK); textbackground(CYAN); gotoxy(6, 6); cprintf(" Main menu "); gotoxy(6, 7); cprintf(" "); gotoxy(6, 8); cprintf(" Status Bar "); gotoxy(6, 9); cprintf(" "); gotoxy(6, 10); cprintf(" Pulldown menu "); gotoxy(6, 11); cprintf(" "); gotoxy(6, 12);cprintf(" Menubar "); gotoxy(6, 13); cprintf(" "); gotoxy(6, 14);cprintf(" Window "); gotoxy(6, 15); cprintf(" "); gotoxy(6, 16);cprintf(" Background "); textcolor(WHITE); textbackground(CYAN); switch (choice) { case 1: gotoxy(6, 6); cprintf(" Main menu "); result = setupcolor(&pref.mainmenucolor, &pref.mainmenubkcolor); break; case 2: gotoxy(6, 8); cprintf(" Status Bar "); result = setupcolor(&pref.statusbarcolor, &pref.statusbarbkcolor); break; case 3: gotoxy(6, 10); cprintf(" Pulldown menu "); result = setupcolor(&pref.pullmenucolor, &pref.pullmenubkcolor); break; case 4: gotoxy(6, 12);cprintf(" Menubar "); result = setupcolor(&pref.menubarcolor, &pref.menubarbkcolor); break; case 5: gotoxy(6, 14);cprintf(" Window "); result = setupcolor(&pref.wincolor, &pref.winbkcolor); break; case 6: gotoxy(6, 16);cprintf(" Background "); result = setupcolor(&pref.color, &pref.bkcolor); break; } /* Up arrow. */ if ((result == 328) || (result == 271)) { if (choice == 1) choice = 6; else choice--; } /* Down arrow. */ if ((result == 336) || (result == 9)) { if (choice == 6) choice = 1; else choice++; } /* Set all options if ESC pressed. */ if (result == 27) break; } while (1); movedata(FP_SEG(buffer), FP_OFF(buffer), _dos_ds, video_base, 4000); mainmenubar(); drawwindow(); redrawwindow(); _setcursortype((!win -> insert) + 1); setcursor; }